@blackcode_sa/metaestetics-api 1.13.5 → 1.13.6

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