@blackcode_sa/metaestetics-api 1.12.68 → 1.13.0

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 (39) hide show
  1. package/dist/admin/index.d.mts +801 -2
  2. package/dist/admin/index.d.ts +801 -2
  3. package/dist/admin/index.js +2332 -153
  4. package/dist/admin/index.mjs +2321 -153
  5. package/dist/index.d.mts +1057 -2
  6. package/dist/index.d.ts +1057 -2
  7. package/dist/index.js +4150 -2117
  8. package/dist/index.mjs +3832 -1810
  9. package/package.json +1 -1
  10. package/src/admin/aggregation/appointment/appointment.aggregation.service.ts +140 -0
  11. package/src/admin/analytics/analytics.admin.service.ts +278 -0
  12. package/src/admin/analytics/index.ts +2 -0
  13. package/src/admin/index.ts +6 -0
  14. package/src/backoffice/services/README.md +17 -0
  15. package/src/backoffice/services/analytics.service.proposal.md +863 -0
  16. package/src/backoffice/services/analytics.service.summary.md +143 -0
  17. package/src/services/analytics/ARCHITECTURE.md +199 -0
  18. package/src/services/analytics/CLOUD_FUNCTIONS.md +225 -0
  19. package/src/services/analytics/GROUPED_ANALYTICS.md +501 -0
  20. package/src/services/analytics/QUICK_START.md +393 -0
  21. package/src/services/analytics/README.md +287 -0
  22. package/src/services/analytics/SUMMARY.md +141 -0
  23. package/src/services/analytics/USAGE_GUIDE.md +518 -0
  24. package/src/services/analytics/analytics-cloud.service.ts +222 -0
  25. package/src/services/analytics/analytics.service.ts +1632 -0
  26. package/src/services/analytics/index.ts +3 -0
  27. package/src/services/analytics/utils/appointment-filtering.utils.ts +138 -0
  28. package/src/services/analytics/utils/cost-calculation.utils.ts +154 -0
  29. package/src/services/analytics/utils/grouping.utils.ts +394 -0
  30. package/src/services/analytics/utils/stored-analytics.utils.ts +347 -0
  31. package/src/services/analytics/utils/time-calculation.utils.ts +186 -0
  32. package/src/services/appointment/appointment.service.ts +50 -6
  33. package/src/services/index.ts +1 -0
  34. package/src/types/analytics/analytics.types.ts +500 -0
  35. package/src/types/analytics/grouped-analytics.types.ts +148 -0
  36. package/src/types/analytics/index.ts +4 -0
  37. package/src/types/analytics/stored-analytics.types.ts +137 -0
  38. package/src/types/index.ts +3 -0
  39. package/src/types/notifications/index.ts +21 -0
@@ -0,0 +1,500 @@
1
+ import { Timestamp } from 'firebase/firestore';
2
+ import { AppointmentStatus, PaymentStatus } from '../appointment';
3
+
4
+ /**
5
+ * Base metrics interface with common properties
6
+ */
7
+ export interface BaseMetrics {
8
+ total: number;
9
+ dateRange?: { start: Date; end: Date };
10
+ }
11
+
12
+ /**
13
+ * Date range filter for analytics queries
14
+ */
15
+ export interface AnalyticsDateRange {
16
+ start: Date;
17
+ end: Date;
18
+ }
19
+
20
+ /**
21
+ * Common filters for analytics queries
22
+ */
23
+ export interface AnalyticsFilters {
24
+ clinicBranchId?: string;
25
+ practitionerId?: string;
26
+ procedureId?: string;
27
+ patientId?: string;
28
+ }
29
+
30
+ /**
31
+ * Grouping period for trend analysis
32
+ */
33
+ export type GroupingPeriod = 'day' | 'week' | 'month';
34
+
35
+ /**
36
+ * Entity type for grouping analytics
37
+ */
38
+ export type EntityType = 'clinic' | 'practitioner' | 'patient' | 'procedure' | 'technology';
39
+
40
+ /**
41
+ * Practitioner Analytics
42
+ * Comprehensive metrics for a practitioner's performance
43
+ */
44
+ export interface PractitionerAnalytics extends BaseMetrics {
45
+ practitionerId: string;
46
+ practitionerName: string;
47
+ totalAppointments: number;
48
+ completedAppointments: number;
49
+ canceledAppointments: number;
50
+ noShowAppointments: number;
51
+ pendingAppointments: number;
52
+ confirmedAppointments: number;
53
+ cancellationRate: number; // percentage
54
+ noShowRate: number; // percentage
55
+ averageBookedTime: number; // minutes
56
+ averageActualTime: number; // minutes
57
+ timeEfficiency: number; // percentage
58
+ totalRevenue: number;
59
+ averageRevenuePerAppointment: number;
60
+ currency: string;
61
+ topProcedures: Array<{
62
+ procedureId: string;
63
+ procedureName: string;
64
+ count: number;
65
+ revenue: number;
66
+ }>;
67
+ patientRetentionRate: number; // percentage
68
+ uniquePatients: number;
69
+ }
70
+
71
+ /**
72
+ * Procedure Analytics
73
+ * Comprehensive metrics for procedure performance
74
+ */
75
+ export interface ProcedureAnalytics extends BaseMetrics {
76
+ procedureId: string;
77
+ procedureName: string;
78
+ procedureFamily: string;
79
+ categoryName: string;
80
+ subcategoryName: string;
81
+ technologyName: string;
82
+ totalAppointments: number;
83
+ completedAppointments: number;
84
+ canceledAppointments: number;
85
+ noShowAppointments: number;
86
+ cancellationRate: number; // percentage
87
+ noShowRate: number; // percentage
88
+ averageCost: number;
89
+ totalRevenue: number;
90
+ averageRevenuePerAppointment: number;
91
+ currency: string;
92
+ averageBookedDuration: number; // minutes
93
+ averageActualDuration: number; // minutes
94
+ productUsage: Array<{
95
+ productId: string;
96
+ productName: string;
97
+ brandName: string;
98
+ totalQuantity: number;
99
+ totalRevenue: number;
100
+ usageCount: number;
101
+ }>;
102
+ }
103
+
104
+ /**
105
+ * Time Efficiency Metrics
106
+ * Analysis of booked time vs actual time spent
107
+ */
108
+ export interface TimeEfficiencyMetrics {
109
+ totalAppointments: number;
110
+ appointmentsWithActualTime: number;
111
+ averageBookedDuration: number; // minutes
112
+ averageActualDuration: number; // minutes
113
+ averageEfficiency: number; // percentage
114
+ totalOverrun: number; // minutes
115
+ totalUnderutilization: number; // minutes
116
+ averageOverrun: number; // minutes
117
+ averageUnderutilization: number; // minutes
118
+ efficiencyDistribution: Array<{
119
+ range: string; // e.g., "0-50%", "50-75%", "75-100%", "100%+"
120
+ count: number;
121
+ percentage: number;
122
+ }>;
123
+ }
124
+
125
+ /**
126
+ * Cancellation Metrics
127
+ * Analysis of appointment cancellations
128
+ */
129
+ export interface CancellationMetrics {
130
+ entityId: string;
131
+ entityName: string;
132
+ entityType: EntityType;
133
+ totalAppointments: number;
134
+ canceledAppointments: number;
135
+ cancellationRate: number; // percentage
136
+ canceledByPatient: number;
137
+ canceledByClinic: number;
138
+ canceledByPractitioner: number;
139
+ canceledRescheduled: number;
140
+ averageCancellationLeadTime: number; // hours
141
+ cancellationReasons: Array<{
142
+ reason: string;
143
+ count: number;
144
+ percentage: number;
145
+ }>;
146
+ }
147
+
148
+ /**
149
+ * No-Show Metrics
150
+ * Analysis of appointment no-shows
151
+ */
152
+ export interface NoShowMetrics {
153
+ entityId: string;
154
+ entityName: string;
155
+ entityType: EntityType;
156
+ totalAppointments: number;
157
+ noShowAppointments: number;
158
+ noShowRate: number; // percentage
159
+ }
160
+
161
+ /**
162
+ * Revenue Metrics
163
+ * Financial analysis and revenue tracking
164
+ */
165
+ export interface RevenueMetrics {
166
+ totalRevenue: number;
167
+ averageRevenuePerAppointment: number;
168
+ totalAppointments: number;
169
+ completedAppointments: number;
170
+ currency: string;
171
+ revenueByStatus: Partial<Record<AppointmentStatus, number>>;
172
+ revenueByPaymentStatus: Partial<Record<PaymentStatus, number>>;
173
+ unpaidRevenue: number;
174
+ refundedRevenue: number;
175
+ totalTax: number;
176
+ totalSubtotal: number;
177
+ }
178
+
179
+ /**
180
+ * Revenue Trend
181
+ * Revenue data over time
182
+ */
183
+ export interface RevenueTrend {
184
+ period: string; // e.g., "2024-01-01", "2024-W01", "2024-01"
185
+ startDate: Date;
186
+ endDate: Date;
187
+ revenue: number;
188
+ appointmentCount: number;
189
+ averageRevenue: number;
190
+ }
191
+
192
+ /**
193
+ * Duration Trend
194
+ * Appointment duration trends over time
195
+ */
196
+ export interface DurationTrend {
197
+ period: string;
198
+ startDate: Date;
199
+ endDate: Date;
200
+ averageBookedDuration: number; // minutes
201
+ averageActualDuration: number; // minutes
202
+ averageEfficiency: number; // percentage
203
+ appointmentCount: number;
204
+ }
205
+
206
+ /**
207
+ * Product Usage Metrics
208
+ * Analysis of product usage in appointments
209
+ */
210
+ export interface ProductUsageMetrics {
211
+ productId: string;
212
+ productName: string;
213
+ brandId: string;
214
+ brandName: string;
215
+ totalQuantity: number;
216
+ totalRevenue: number;
217
+ averagePrice: number;
218
+ currency: string;
219
+ usageCount: number; // number of appointments using this product
220
+ averageQuantityPerAppointment: number;
221
+ usageByProcedure: Array<{
222
+ procedureId: string;
223
+ procedureName: string;
224
+ count: number;
225
+ totalQuantity: number;
226
+ }>;
227
+ }
228
+
229
+ /**
230
+ * Product Revenue Metrics
231
+ * Revenue contribution by product
232
+ */
233
+ export interface ProductRevenueMetrics {
234
+ productId: string;
235
+ productName: string;
236
+ brandName: string;
237
+ totalRevenue: number;
238
+ currency: string;
239
+ usageCount: number;
240
+ averageRevenuePerUsage: number;
241
+ }
242
+
243
+ /**
244
+ * Product Usage by Procedure
245
+ * Product usage patterns for specific procedures
246
+ */
247
+ export interface ProductUsageByProcedure {
248
+ procedureId: string;
249
+ procedureName: string;
250
+ products: Array<{
251
+ productId: string;
252
+ productName: string;
253
+ brandName: string;
254
+ totalQuantity: number;
255
+ totalRevenue: number;
256
+ usageCount: number;
257
+ }>;
258
+ }
259
+
260
+ /**
261
+ * Patient Analytics
262
+ * Comprehensive patient metrics
263
+ */
264
+ export interface PatientAnalytics {
265
+ patientId: string;
266
+ patientName: string;
267
+ totalAppointments: number;
268
+ completedAppointments: number;
269
+ canceledAppointments: number;
270
+ noShowAppointments: number;
271
+ cancellationRate: number; // percentage
272
+ noShowRate: number; // percentage
273
+ totalRevenue: number;
274
+ averageRevenuePerAppointment: number;
275
+ currency: string;
276
+ lifetimeValue: number;
277
+ firstAppointmentDate: Date | null;
278
+ lastAppointmentDate: Date | null;
279
+ averageDaysBetweenAppointments: number | null;
280
+ uniquePractitioners: number;
281
+ uniqueClinics: number;
282
+ favoriteProcedures: Array<{
283
+ procedureId: string;
284
+ procedureName: string;
285
+ count: number;
286
+ }>;
287
+ }
288
+
289
+ /**
290
+ * Patient Lifetime Value Metrics
291
+ * Patient value analysis
292
+ */
293
+ export interface PatientLifetimeValueMetrics {
294
+ totalPatients: number;
295
+ averageLifetimeValue: number;
296
+ currency: string;
297
+ topPatients: Array<{
298
+ patientId: string;
299
+ patientName: string;
300
+ lifetimeValue: number;
301
+ appointmentCount: number;
302
+ }>;
303
+ valueDistribution: Array<{
304
+ range: string; // e.g., "0-500", "500-1000", "1000+"
305
+ count: number;
306
+ percentage: number;
307
+ }>;
308
+ }
309
+
310
+ /**
311
+ * Patient Retention Metrics
312
+ * Patient retention and return analysis
313
+ */
314
+ export interface PatientRetentionMetrics {
315
+ totalPatients: number;
316
+ newPatients: number;
317
+ returningPatients: number;
318
+ retentionRate: number; // percentage
319
+ averageAppointmentsPerPatient: number;
320
+ patientsByAppointmentCount: Array<{
321
+ appointmentCount: number;
322
+ patientCount: number;
323
+ percentage: number;
324
+ }>;
325
+ }
326
+
327
+ /**
328
+ * Cost Per Patient Metrics
329
+ * Cost analysis per patient
330
+ */
331
+ export interface CostPerPatientMetrics {
332
+ totalPatients: number;
333
+ totalRevenue: number;
334
+ averageCostPerPatient: number;
335
+ currency: string;
336
+ costDistribution: Array<{
337
+ range: string;
338
+ patientCount: number;
339
+ percentage: number;
340
+ }>;
341
+ patientCosts?: Array<{
342
+ patientId: string;
343
+ patientName: string;
344
+ totalCost: number;
345
+ appointmentCount: number;
346
+ averageCost: number;
347
+ }>;
348
+ }
349
+
350
+ /**
351
+ * Payment Status Breakdown
352
+ * Analysis of payment statuses
353
+ */
354
+ export interface PaymentStatusBreakdown {
355
+ totalAppointments: number;
356
+ byStatus: Partial<Record<PaymentStatus, {
357
+ count: number;
358
+ percentage: number;
359
+ totalRevenue: number;
360
+ }>>;
361
+ unpaidCount: number;
362
+ unpaidRevenue: number;
363
+ paidCount: number;
364
+ paidRevenue: number;
365
+ partiallyPaidCount: number;
366
+ partiallyPaidRevenue: number;
367
+ refundedCount: number;
368
+ refundedRevenue: number;
369
+ }
370
+
371
+ /**
372
+ * Clinic Analytics
373
+ * Comprehensive clinic performance metrics
374
+ */
375
+ export interface ClinicAnalytics {
376
+ clinicBranchId: string;
377
+ clinicName: string;
378
+ totalAppointments: number;
379
+ completedAppointments: number;
380
+ canceledAppointments: number;
381
+ noShowAppointments: number;
382
+ cancellationRate: number; // percentage
383
+ noShowRate: number; // percentage
384
+ totalRevenue: number;
385
+ averageRevenuePerAppointment: number;
386
+ currency: string;
387
+ practitionerCount: number;
388
+ patientCount: number;
389
+ procedureCount: number;
390
+ topPractitioners: Array<{
391
+ practitionerId: string;
392
+ practitionerName: string;
393
+ appointmentCount: number;
394
+ revenue: number;
395
+ }>;
396
+ topProcedures: Array<{
397
+ procedureId: string;
398
+ procedureName: string;
399
+ appointmentCount: number;
400
+ revenue: number;
401
+ }>;
402
+ }
403
+
404
+ /**
405
+ * Clinic Comparison Metrics
406
+ * Comparison data for multiple clinics
407
+ */
408
+ export interface ClinicComparisonMetrics {
409
+ clinicBranchId: string;
410
+ clinicName: string;
411
+ totalAppointments: number;
412
+ completedAppointments: number;
413
+ cancellationRate: number;
414
+ noShowRate: number;
415
+ totalRevenue: number;
416
+ averageRevenuePerAppointment: number;
417
+ practitionerCount: number;
418
+ patientCount: number;
419
+ efficiency: number; // percentage
420
+ }
421
+
422
+ /**
423
+ * Procedure Popularity
424
+ * Popularity metrics for procedures
425
+ */
426
+ export interface ProcedurePopularity {
427
+ procedureId: string;
428
+ procedureName: string;
429
+ categoryName: string;
430
+ subcategoryName: string;
431
+ technologyName: string;
432
+ appointmentCount: number;
433
+ completedCount: number;
434
+ rank: number;
435
+ }
436
+
437
+ /**
438
+ * Procedure Profitability
439
+ * Profitability metrics for procedures
440
+ */
441
+ export interface ProcedureProfitability {
442
+ procedureId: string;
443
+ procedureName: string;
444
+ categoryName: string;
445
+ subcategoryName: string;
446
+ technologyName: string;
447
+ totalRevenue: number;
448
+ averageRevenue: number;
449
+ appointmentCount: number;
450
+ rank: number;
451
+ }
452
+
453
+ /**
454
+ * Cancellation Reason Statistics
455
+ * Breakdown of cancellation reasons
456
+ */
457
+ export interface CancellationReasonStats {
458
+ reason: string;
459
+ count: number;
460
+ percentage: number;
461
+ averageLeadTime: number; // hours
462
+ }
463
+
464
+ /**
465
+ * Dashboard Analytics
466
+ * Comprehensive dashboard data aggregation
467
+ */
468
+ export interface DashboardAnalytics {
469
+ overview: {
470
+ totalAppointments: number;
471
+ completedAppointments: number;
472
+ canceledAppointments: number;
473
+ noShowAppointments: number;
474
+ pendingAppointments: number;
475
+ confirmedAppointments: number;
476
+ totalRevenue: number;
477
+ averageRevenuePerAppointment: number;
478
+ currency: string;
479
+ uniquePatients: number;
480
+ uniquePractitioners: number;
481
+ uniqueProcedures: number;
482
+ cancellationRate: number;
483
+ noShowRate: number;
484
+ };
485
+ practitionerMetrics: PractitionerAnalytics[];
486
+ procedureMetrics: ProcedureAnalytics[];
487
+ cancellationMetrics: CancellationMetrics;
488
+ noShowMetrics: NoShowMetrics;
489
+ revenueTrends: RevenueTrend[];
490
+ timeEfficiency: TimeEfficiencyMetrics;
491
+ topProducts: ProductUsageMetrics[];
492
+ recentActivity: Array<{
493
+ type: 'appointment' | 'cancellation' | 'completion' | 'no_show';
494
+ date: Date;
495
+ description: string;
496
+ entityId?: string;
497
+ entityName?: string;
498
+ }>;
499
+ }
500
+
@@ -0,0 +1,148 @@
1
+ import { EntityType } from './analytics.types';
2
+
3
+ /**
4
+ * Base interface for grouped analytics results
5
+ * All grouped analytics share common entity identification
6
+ */
7
+ export interface GroupedAnalyticsBase {
8
+ entityId: string;
9
+ entityName: string;
10
+ entityType: EntityType;
11
+ }
12
+
13
+ /**
14
+ * Grouped Revenue Metrics
15
+ * Revenue analytics grouped by clinic, practitioner, procedure, or patient
16
+ */
17
+ export interface GroupedRevenueMetrics extends GroupedAnalyticsBase {
18
+ totalRevenue: number;
19
+ averageRevenuePerAppointment: number;
20
+ totalAppointments: number;
21
+ completedAppointments: number;
22
+ currency: string;
23
+ unpaidRevenue: number;
24
+ refundedRevenue: number;
25
+ totalTax: number;
26
+ totalSubtotal: number;
27
+ }
28
+
29
+ /**
30
+ * Grouped Product Usage Metrics
31
+ * Product usage analytics grouped by clinic, practitioner, procedure, or patient
32
+ */
33
+ export interface GroupedProductUsageMetrics extends GroupedAnalyticsBase {
34
+ totalProductsUsed: number;
35
+ uniqueProducts: number;
36
+ totalProductRevenue: number;
37
+ totalProductQuantity: number;
38
+ averageProductsPerAppointment: number;
39
+ topProducts: Array<{
40
+ productId: string;
41
+ productName: string;
42
+ brandName: string;
43
+ totalQuantity: number;
44
+ totalRevenue: number;
45
+ usageCount: number;
46
+ }>;
47
+ }
48
+
49
+ /**
50
+ * Grouped Patient Retention Metrics
51
+ * Patient retention analytics grouped by clinic, practitioner, or procedure
52
+ */
53
+ export interface GroupedPatientRetentionMetrics extends GroupedAnalyticsBase {
54
+ totalPatients: number;
55
+ newPatients: number;
56
+ returningPatients: number;
57
+ retentionRate: number; // percentage
58
+ averageAppointmentsPerPatient: number;
59
+ patientsByAppointmentCount: Array<{
60
+ appointmentCount: number;
61
+ patientCount: number;
62
+ percentage: number;
63
+ }>;
64
+ }
65
+
66
+ /**
67
+ * Grouped Time Efficiency Metrics
68
+ * Time efficiency analytics grouped by clinic, practitioner, procedure, or patient
69
+ */
70
+ export interface GroupedTimeEfficiencyMetrics extends GroupedAnalyticsBase {
71
+ totalAppointments: number;
72
+ appointmentsWithActualTime: number;
73
+ averageBookedDuration: number; // minutes
74
+ averageActualDuration: number; // minutes
75
+ averageEfficiency: number; // percentage
76
+ totalOverrun: number; // minutes
77
+ totalUnderutilization: number; // minutes
78
+ averageOverrun: number; // minutes
79
+ averageUnderutilization: number; // minutes
80
+ }
81
+
82
+ /**
83
+ * Grouped Patient Behavior Metrics
84
+ * Patient behavior (no-show, cancellation) grouped by clinic, practitioner, or procedure
85
+ */
86
+ export interface GroupedPatientBehaviorMetrics extends GroupedAnalyticsBase {
87
+ totalPatients: number;
88
+ patientsWithNoShows: number;
89
+ patientsWithCancellations: number;
90
+ averageNoShowRate: number; // percentage (average across patients)
91
+ averageCancellationRate: number; // percentage (average across patients)
92
+ topNoShowPatients: Array<{
93
+ patientId: string;
94
+ patientName: string;
95
+ noShowCount: number;
96
+ totalAppointments: number;
97
+ noShowRate: number;
98
+ }>;
99
+ topCancellationPatients: Array<{
100
+ patientId: string;
101
+ patientName: string;
102
+ cancellationCount: number;
103
+ totalAppointments: number;
104
+ cancellationRate: number;
105
+ }>;
106
+ }
107
+
108
+ /**
109
+ * Grouped Procedure Performance Metrics
110
+ * Procedure performance grouped by clinic or practitioner
111
+ */
112
+ export interface GroupedProcedurePerformanceMetrics extends GroupedAnalyticsBase {
113
+ totalProcedures: number;
114
+ totalAppointments: number;
115
+ completedAppointments: number;
116
+ totalRevenue: number;
117
+ averageRevenuePerProcedure: number;
118
+ topProcedures: Array<{
119
+ procedureId: string;
120
+ procedureName: string;
121
+ appointmentCount: number;
122
+ revenue: number;
123
+ cancellationRate: number;
124
+ noShowRate: number;
125
+ }>;
126
+ }
127
+
128
+ /**
129
+ * Grouped Practitioner Performance Metrics
130
+ * Practitioner performance grouped by clinic
131
+ */
132
+ export interface GroupedPractitionerPerformanceMetrics extends GroupedAnalyticsBase {
133
+ totalPractitioners: number;
134
+ totalAppointments: number;
135
+ completedAppointments: number;
136
+ totalRevenue: number;
137
+ averageRevenuePerPractitioner: number;
138
+ topPractitioners: Array<{
139
+ practitionerId: string;
140
+ practitionerName: string;
141
+ appointmentCount: number;
142
+ revenue: number;
143
+ cancellationRate: number;
144
+ noShowRate: number;
145
+ timeEfficiency: number;
146
+ }>;
147
+ }
148
+
@@ -0,0 +1,4 @@
1
+ export * from './analytics.types';
2
+ export * from './stored-analytics.types';
3
+ export * from './grouped-analytics.types';
4
+