@blackcode_sa/metaestetics-api 1.13.5 → 1.13.8

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 (295) hide show
  1. package/dist/admin/index.d.mts +20 -1
  2. package/dist/admin/index.d.ts +20 -1
  3. package/dist/admin/index.js +217 -1
  4. package/dist/admin/index.mjs +217 -1
  5. package/dist/index.d.mts +26 -3
  6. package/dist/index.d.ts +26 -3
  7. package/dist/index.js +168 -6
  8. package/dist/index.mjs +168 -6
  9. package/package.json +121 -121
  10. package/src/__mocks__/firstore.ts +10 -10
  11. package/src/admin/aggregation/README.md +79 -79
  12. package/src/admin/aggregation/appointment/README.md +128 -128
  13. package/src/admin/aggregation/appointment/appointment.aggregation.service.ts +1984 -1984
  14. package/src/admin/aggregation/appointment/index.ts +1 -1
  15. package/src/admin/aggregation/clinic/README.md +52 -52
  16. package/src/admin/aggregation/clinic/clinic.aggregation.service.ts +966 -703
  17. package/src/admin/aggregation/clinic/index.ts +1 -1
  18. package/src/admin/aggregation/forms/README.md +13 -13
  19. package/src/admin/aggregation/forms/filled-forms.aggregation.service.ts +322 -322
  20. package/src/admin/aggregation/forms/index.ts +1 -1
  21. package/src/admin/aggregation/index.ts +8 -8
  22. package/src/admin/aggregation/patient/README.md +27 -27
  23. package/src/admin/aggregation/patient/index.ts +1 -1
  24. package/src/admin/aggregation/patient/patient.aggregation.service.ts +141 -141
  25. package/src/admin/aggregation/practitioner/README.md +42 -42
  26. package/src/admin/aggregation/practitioner/index.ts +1 -1
  27. package/src/admin/aggregation/practitioner/practitioner.aggregation.service.ts +433 -433
  28. package/src/admin/aggregation/practitioner-invite/index.ts +1 -1
  29. package/src/admin/aggregation/practitioner-invite/practitioner-invite.aggregation.service.ts +961 -961
  30. package/src/admin/aggregation/procedure/README.md +43 -43
  31. package/src/admin/aggregation/procedure/index.ts +1 -1
  32. package/src/admin/aggregation/procedure/procedure.aggregation.service.ts +702 -702
  33. package/src/admin/aggregation/reviews/index.ts +1 -1
  34. package/src/admin/aggregation/reviews/reviews.aggregation.service.ts +689 -689
  35. package/src/admin/analytics/analytics.admin.service.ts +278 -278
  36. package/src/admin/analytics/index.ts +2 -2
  37. package/src/admin/booking/README.md +125 -125
  38. package/src/admin/booking/booking.admin.ts +1037 -1037
  39. package/src/admin/booking/booking.calculator.ts +712 -712
  40. package/src/admin/booking/booking.types.ts +59 -59
  41. package/src/admin/booking/index.ts +3 -3
  42. package/src/admin/booking/timezones-problem.md +185 -185
  43. package/src/admin/calendar/README.md +7 -7
  44. package/src/admin/calendar/calendar.admin.service.ts +345 -345
  45. package/src/admin/calendar/index.ts +1 -1
  46. package/src/admin/documentation-templates/document-manager.admin.ts +260 -260
  47. package/src/admin/documentation-templates/index.ts +1 -1
  48. package/src/admin/free-consultation/free-consultation-utils.admin.ts +148 -148
  49. package/src/admin/free-consultation/index.ts +1 -1
  50. package/src/admin/index.ts +81 -81
  51. package/src/admin/logger/index.ts +78 -78
  52. package/src/admin/mailing/README.md +95 -95
  53. package/src/admin/mailing/appointment/appointment.mailing.service.ts +732 -732
  54. package/src/admin/mailing/appointment/index.ts +1 -1
  55. package/src/admin/mailing/appointment/templates/patient/appointment-confirmed.html +40 -40
  56. package/src/admin/mailing/base.mailing.service.ts +208 -208
  57. package/src/admin/mailing/index.ts +3 -3
  58. package/src/admin/mailing/practitionerInvite/existing-practitioner-invite.mailing.ts +611 -611
  59. package/src/admin/mailing/practitionerInvite/index.ts +2 -2
  60. package/src/admin/mailing/practitionerInvite/practitionerInvite.mailing.ts +395 -395
  61. package/src/admin/mailing/practitionerInvite/templates/existing-practitioner-invitation.template.ts +155 -155
  62. package/src/admin/mailing/practitionerInvite/templates/invitation.template.ts +101 -101
  63. package/src/admin/mailing/practitionerInvite/templates/invite-accepted-notification.template.ts +228 -228
  64. package/src/admin/mailing/practitionerInvite/templates/invite-rejected-notification.template.ts +242 -242
  65. package/src/admin/notifications/index.ts +1 -1
  66. package/src/admin/notifications/notifications.admin.ts +710 -710
  67. package/src/admin/requirements/README.md +128 -128
  68. package/src/admin/requirements/index.ts +1 -1
  69. package/src/admin/requirements/patient-requirements.admin.service.ts +475 -475
  70. package/src/admin/users/index.ts +1 -1
  71. package/src/admin/users/user-profile.admin.ts +405 -405
  72. package/src/backoffice/constants/certification.constants.ts +13 -13
  73. package/src/backoffice/constants/index.ts +1 -1
  74. package/src/backoffice/errors/backoffice.errors.ts +181 -181
  75. package/src/backoffice/errors/index.ts +1 -1
  76. package/src/backoffice/expo-safe/README.md +26 -26
  77. package/src/backoffice/expo-safe/index.ts +41 -41
  78. package/src/backoffice/index.ts +5 -5
  79. package/src/backoffice/services/FIXES_README.md +102 -102
  80. package/src/backoffice/services/README.md +57 -57
  81. package/src/backoffice/services/analytics.service.proposal.md +863 -863
  82. package/src/backoffice/services/analytics.service.summary.md +143 -143
  83. package/src/backoffice/services/brand.service.ts +256 -256
  84. package/src/backoffice/services/category.service.ts +384 -384
  85. package/src/backoffice/services/constants.service.ts +385 -385
  86. package/src/backoffice/services/documentation-template.service.ts +202 -202
  87. package/src/backoffice/services/index.ts +10 -10
  88. package/src/backoffice/services/migrate-products.ts +116 -116
  89. package/src/backoffice/services/product.service.ts +553 -553
  90. package/src/backoffice/services/requirement.service.ts +235 -235
  91. package/src/backoffice/services/subcategory.service.ts +461 -461
  92. package/src/backoffice/services/technology.service.ts +1151 -1151
  93. package/src/backoffice/types/README.md +12 -12
  94. package/src/backoffice/types/admin-constants.types.ts +69 -69
  95. package/src/backoffice/types/brand.types.ts +29 -29
  96. package/src/backoffice/types/category.types.ts +67 -67
  97. package/src/backoffice/types/documentation-templates.types.ts +28 -28
  98. package/src/backoffice/types/index.ts +10 -10
  99. package/src/backoffice/types/procedure-product.types.ts +38 -38
  100. package/src/backoffice/types/product.types.ts +240 -240
  101. package/src/backoffice/types/requirement.types.ts +63 -63
  102. package/src/backoffice/types/static/README.md +18 -18
  103. package/src/backoffice/types/static/blocking-condition.types.ts +21 -21
  104. package/src/backoffice/types/static/certification.types.ts +37 -37
  105. package/src/backoffice/types/static/contraindication.types.ts +19 -19
  106. package/src/backoffice/types/static/index.ts +6 -6
  107. package/src/backoffice/types/static/pricing.types.ts +16 -16
  108. package/src/backoffice/types/static/procedure-family.types.ts +14 -14
  109. package/src/backoffice/types/static/treatment-benefit.types.ts +22 -22
  110. package/src/backoffice/types/subcategory.types.ts +34 -34
  111. package/src/backoffice/types/technology.types.ts +168 -168
  112. package/src/backoffice/validations/index.ts +1 -1
  113. package/src/backoffice/validations/schemas.ts +164 -164
  114. package/src/config/__mocks__/firebase.ts +99 -99
  115. package/src/config/firebase.ts +78 -78
  116. package/src/config/index.ts +9 -9
  117. package/src/errors/auth.error.ts +6 -6
  118. package/src/errors/auth.errors.ts +211 -200
  119. package/src/errors/clinic.errors.ts +32 -32
  120. package/src/errors/firebase.errors.ts +47 -47
  121. package/src/errors/user.errors.ts +99 -99
  122. package/src/index.backup.ts +407 -407
  123. package/src/index.ts +6 -6
  124. package/src/locales/en.ts +31 -31
  125. package/src/recommender/admin/index.ts +1 -1
  126. package/src/recommender/admin/services/recommender.service.admin.ts +5 -5
  127. package/src/recommender/front/index.ts +1 -1
  128. package/src/recommender/front/services/onboarding.service.ts +5 -5
  129. package/src/recommender/front/services/recommender.service.ts +3 -3
  130. package/src/recommender/index.ts +1 -1
  131. package/src/services/PATIENTAUTH.MD +197 -197
  132. package/src/services/README.md +106 -106
  133. package/src/services/__tests__/auth/auth.mock.test.ts +17 -17
  134. package/src/services/__tests__/auth/auth.setup.ts +293 -293
  135. package/src/services/__tests__/auth.service.test.ts +346 -346
  136. package/src/services/__tests__/base.service.test.ts +77 -77
  137. package/src/services/__tests__/user.service.test.ts +528 -528
  138. package/src/services/analytics/ARCHITECTURE.md +199 -199
  139. package/src/services/analytics/CLOUD_FUNCTIONS.md +225 -225
  140. package/src/services/analytics/GROUPED_ANALYTICS.md +501 -501
  141. package/src/services/analytics/QUICK_START.md +393 -393
  142. package/src/services/analytics/README.md +304 -304
  143. package/src/services/analytics/SUMMARY.md +141 -141
  144. package/src/services/analytics/TRENDS.md +380 -380
  145. package/src/services/analytics/USAGE_GUIDE.md +518 -518
  146. package/src/services/analytics/analytics-cloud.service.ts +222 -222
  147. package/src/services/analytics/analytics.service.ts +2142 -2142
  148. package/src/services/analytics/index.ts +4 -4
  149. package/src/services/analytics/review-analytics.service.ts +941 -941
  150. package/src/services/analytics/utils/appointment-filtering.utils.ts +138 -138
  151. package/src/services/analytics/utils/cost-calculation.utils.ts +182 -182
  152. package/src/services/analytics/utils/grouping.utils.ts +434 -434
  153. package/src/services/analytics/utils/stored-analytics.utils.ts +347 -347
  154. package/src/services/analytics/utils/time-calculation.utils.ts +186 -186
  155. package/src/services/analytics/utils/trend-calculation.utils.ts +200 -200
  156. package/src/services/appointment/README.md +17 -17
  157. package/src/services/appointment/appointment.service.ts +2558 -2558
  158. package/src/services/appointment/index.ts +1 -1
  159. package/src/services/appointment/utils/appointment.utils.ts +552 -552
  160. package/src/services/appointment/utils/extended-procedure.utils.ts +314 -314
  161. package/src/services/appointment/utils/form-initialization.utils.ts +225 -225
  162. package/src/services/appointment/utils/recommended-procedure.utils.ts +195 -195
  163. package/src/services/appointment/utils/zone-management.utils.ts +353 -353
  164. package/src/services/appointment/utils/zone-photo.utils.ts +152 -152
  165. package/src/services/auth/auth.service.ts +1043 -989
  166. package/src/services/auth/auth.v2.service.ts +961 -961
  167. package/src/services/auth/index.ts +7 -7
  168. package/src/services/auth/utils/error.utils.ts +90 -90
  169. package/src/services/auth/utils/firebase.utils.ts +49 -49
  170. package/src/services/auth/utils/index.ts +21 -21
  171. package/src/services/auth/utils/practitioner.utils.ts +125 -125
  172. package/src/services/base.service.ts +41 -41
  173. package/src/services/calendar/calendar.service.ts +1077 -1077
  174. package/src/services/calendar/calendar.v2.service.ts +1683 -1683
  175. package/src/services/calendar/calendar.v3.service.ts +313 -313
  176. package/src/services/calendar/externalCalendar.service.ts +178 -178
  177. package/src/services/calendar/index.ts +5 -5
  178. package/src/services/calendar/synced-calendars.service.ts +743 -743
  179. package/src/services/calendar/utils/appointment.utils.ts +265 -265
  180. package/src/services/calendar/utils/calendar-event.utils.ts +646 -646
  181. package/src/services/calendar/utils/clinic.utils.ts +237 -237
  182. package/src/services/calendar/utils/docs.utils.ts +157 -157
  183. package/src/services/calendar/utils/google-calendar.utils.ts +697 -697
  184. package/src/services/calendar/utils/index.ts +8 -8
  185. package/src/services/calendar/utils/patient.utils.ts +198 -198
  186. package/src/services/calendar/utils/practitioner.utils.ts +221 -221
  187. package/src/services/calendar/utils/synced-calendar.utils.ts +472 -472
  188. package/src/services/clinic/README.md +204 -204
  189. package/src/services/clinic/__tests__/clinic-admin.service.test.ts +287 -287
  190. package/src/services/clinic/__tests__/clinic-group.service.test.ts +352 -352
  191. package/src/services/clinic/__tests__/clinic.service.test.ts +354 -354
  192. package/src/services/clinic/billing-transactions.service.ts +217 -217
  193. package/src/services/clinic/clinic-admin.service.ts +202 -202
  194. package/src/services/clinic/clinic-group.service.ts +310 -310
  195. package/src/services/clinic/clinic.service.ts +708 -708
  196. package/src/services/clinic/index.ts +5 -5
  197. package/src/services/clinic/practitioner-invite.service.ts +519 -519
  198. package/src/services/clinic/utils/admin.utils.ts +551 -551
  199. package/src/services/clinic/utils/clinic-group.utils.ts +646 -646
  200. package/src/services/clinic/utils/clinic.utils.ts +949 -949
  201. package/src/services/clinic/utils/filter.utils.d.ts +23 -23
  202. package/src/services/clinic/utils/filter.utils.ts +446 -446
  203. package/src/services/clinic/utils/index.ts +11 -11
  204. package/src/services/clinic/utils/photos.utils.ts +188 -188
  205. package/src/services/clinic/utils/search.utils.ts +84 -84
  206. package/src/services/clinic/utils/tag.utils.ts +124 -124
  207. package/src/services/documentation-templates/documentation-template.service.ts +537 -537
  208. package/src/services/documentation-templates/filled-document.service.ts +587 -587
  209. package/src/services/documentation-templates/index.ts +2 -2
  210. package/src/services/index.ts +14 -14
  211. package/src/services/media/index.ts +1 -1
  212. package/src/services/media/media.service.ts +418 -418
  213. package/src/services/notifications/__tests__/notification.service.test.ts +242 -242
  214. package/src/services/notifications/index.ts +1 -1
  215. package/src/services/notifications/notification.service.ts +215 -215
  216. package/src/services/patient/README.md +48 -48
  217. package/src/services/patient/To-Do.md +43 -43
  218. package/src/services/patient/__tests__/patient.service.test.ts +294 -294
  219. package/src/services/patient/index.ts +2 -2
  220. package/src/services/patient/patient.service.ts +883 -883
  221. package/src/services/patient/patientRequirements.service.ts +285 -285
  222. package/src/services/patient/utils/aesthetic-analysis.utils.ts +176 -176
  223. package/src/services/patient/utils/clinic.utils.ts +80 -80
  224. package/src/services/patient/utils/docs.utils.ts +142 -142
  225. package/src/services/patient/utils/index.ts +9 -9
  226. package/src/services/patient/utils/location.utils.ts +126 -126
  227. package/src/services/patient/utils/medical-stuff.utils.ts +143 -143
  228. package/src/services/patient/utils/medical.utils.ts +458 -458
  229. package/src/services/patient/utils/practitioner.utils.ts +260 -260
  230. package/src/services/patient/utils/profile.utils.ts +510 -510
  231. package/src/services/patient/utils/sensitive.utils.ts +260 -260
  232. package/src/services/patient/utils/token.utils.ts +211 -211
  233. package/src/services/practitioner/README.md +145 -145
  234. package/src/services/practitioner/index.ts +1 -1
  235. package/src/services/practitioner/practitioner.service.ts +1799 -1742
  236. package/src/services/procedure/README.md +163 -163
  237. package/src/services/procedure/index.ts +1 -1
  238. package/src/services/procedure/procedure.service.ts +2307 -2200
  239. package/src/services/reviews/index.ts +1 -1
  240. package/src/services/reviews/reviews.service.ts +734 -734
  241. package/src/services/user/index.ts +1 -1
  242. package/src/services/user/user.service.ts +489 -489
  243. package/src/services/user/user.v2.service.ts +466 -466
  244. package/src/types/analytics/analytics.types.ts +597 -597
  245. package/src/types/analytics/grouped-analytics.types.ts +173 -173
  246. package/src/types/analytics/index.ts +4 -4
  247. package/src/types/analytics/stored-analytics.types.ts +137 -137
  248. package/src/types/appointment/index.ts +480 -480
  249. package/src/types/calendar/index.ts +258 -258
  250. package/src/types/calendar/synced-calendar.types.ts +66 -66
  251. package/src/types/clinic/index.ts +498 -498
  252. package/src/types/clinic/practitioner-invite.types.ts +91 -91
  253. package/src/types/clinic/preferences.types.ts +159 -159
  254. package/src/types/clinic/to-do +3 -3
  255. package/src/types/documentation-templates/index.ts +308 -308
  256. package/src/types/index.ts +47 -47
  257. package/src/types/notifications/README.md +77 -77
  258. package/src/types/notifications/index.ts +286 -286
  259. package/src/types/patient/aesthetic-analysis.types.ts +66 -66
  260. package/src/types/patient/allergies.ts +58 -58
  261. package/src/types/patient/index.ts +275 -275
  262. package/src/types/patient/medical-info.types.ts +152 -152
  263. package/src/types/patient/patient-requirements.ts +92 -92
  264. package/src/types/patient/token.types.ts +61 -61
  265. package/src/types/practitioner/index.ts +206 -206
  266. package/src/types/procedure/index.ts +181 -181
  267. package/src/types/profile/index.ts +39 -39
  268. package/src/types/reviews/index.ts +132 -132
  269. package/src/types/tz-lookup.d.ts +4 -4
  270. package/src/types/user/index.ts +38 -38
  271. package/src/utils/TIMESTAMPS.md +176 -176
  272. package/src/utils/TimestampUtils.ts +241 -241
  273. package/src/utils/index.ts +1 -1
  274. package/src/validations/appointment.schema.ts +574 -574
  275. package/src/validations/calendar.schema.ts +225 -225
  276. package/src/validations/clinic.schema.ts +494 -494
  277. package/src/validations/common.schema.ts +25 -25
  278. package/src/validations/documentation-templates/index.ts +1 -1
  279. package/src/validations/documentation-templates/template.schema.ts +220 -220
  280. package/src/validations/documentation-templates.schema.ts +10 -10
  281. package/src/validations/index.ts +20 -20
  282. package/src/validations/media.schema.ts +10 -10
  283. package/src/validations/notification.schema.ts +90 -90
  284. package/src/validations/patient/aesthetic-analysis.schema.ts +55 -55
  285. package/src/validations/patient/medical-info.schema.ts +125 -125
  286. package/src/validations/patient/patient-requirements.schema.ts +84 -84
  287. package/src/validations/patient/token.schema.ts +29 -29
  288. package/src/validations/patient.schema.ts +217 -217
  289. package/src/validations/practitioner.schema.ts +222 -222
  290. package/src/validations/procedure-product.schema.ts +41 -41
  291. package/src/validations/procedure.schema.ts +124 -124
  292. package/src/validations/profile-info.schema.ts +41 -41
  293. package/src/validations/reviews.schema.ts +195 -195
  294. package/src/validations/schemas.ts +104 -104
  295. 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
+