@blackcode_sa/metaestetics-api 1.12.67 → 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 (47) 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/backoffice/index.d.mts +40 -0
  6. package/dist/backoffice/index.d.ts +40 -0
  7. package/dist/backoffice/index.js +118 -18
  8. package/dist/backoffice/index.mjs +118 -20
  9. package/dist/index.d.mts +1097 -2
  10. package/dist/index.d.ts +1097 -2
  11. package/dist/index.js +4224 -2091
  12. package/dist/index.mjs +3941 -1821
  13. package/package.json +1 -1
  14. package/src/admin/aggregation/appointment/appointment.aggregation.service.ts +140 -0
  15. package/src/admin/analytics/analytics.admin.service.ts +278 -0
  16. package/src/admin/analytics/index.ts +2 -0
  17. package/src/admin/index.ts +6 -0
  18. package/src/backoffice/services/README.md +17 -0
  19. package/src/backoffice/services/analytics.service.proposal.md +863 -0
  20. package/src/backoffice/services/analytics.service.summary.md +143 -0
  21. package/src/backoffice/services/category.service.ts +49 -6
  22. package/src/backoffice/services/subcategory.service.ts +50 -6
  23. package/src/backoffice/services/technology.service.ts +53 -6
  24. package/src/services/analytics/ARCHITECTURE.md +199 -0
  25. package/src/services/analytics/CLOUD_FUNCTIONS.md +225 -0
  26. package/src/services/analytics/GROUPED_ANALYTICS.md +501 -0
  27. package/src/services/analytics/QUICK_START.md +393 -0
  28. package/src/services/analytics/README.md +287 -0
  29. package/src/services/analytics/SUMMARY.md +141 -0
  30. package/src/services/analytics/USAGE_GUIDE.md +518 -0
  31. package/src/services/analytics/analytics-cloud.service.ts +222 -0
  32. package/src/services/analytics/analytics.service.ts +1632 -0
  33. package/src/services/analytics/index.ts +3 -0
  34. package/src/services/analytics/utils/appointment-filtering.utils.ts +138 -0
  35. package/src/services/analytics/utils/cost-calculation.utils.ts +154 -0
  36. package/src/services/analytics/utils/grouping.utils.ts +394 -0
  37. package/src/services/analytics/utils/stored-analytics.utils.ts +347 -0
  38. package/src/services/analytics/utils/time-calculation.utils.ts +186 -0
  39. package/src/services/appointment/appointment.service.ts +50 -6
  40. package/src/services/index.ts +1 -0
  41. package/src/services/procedure/procedure.service.ts +3 -3
  42. package/src/types/analytics/analytics.types.ts +500 -0
  43. package/src/types/analytics/grouped-analytics.types.ts +148 -0
  44. package/src/types/analytics/index.ts +4 -0
  45. package/src/types/analytics/stored-analytics.types.ts +137 -0
  46. package/src/types/index.ts +3 -0
  47. package/src/types/notifications/index.ts +21 -0
@@ -977,6 +977,8 @@ interface PractitionerInvite {
977
977
  cancelledAt?: Timestamp | null;
978
978
  }
979
979
 
980
+ declare const CLINICS_COLLECTION = "clinics";
981
+
980
982
  /**
981
983
  * Interface for clinic contact information
982
984
  */
@@ -2039,6 +2041,732 @@ interface PatientRequirementInstance {
2039
2041
  */
2040
2042
  declare const PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME = "patientRequirements";
2041
2043
 
2044
+ /**
2045
+ * Base metrics interface with common properties
2046
+ */
2047
+ interface BaseMetrics {
2048
+ total: number;
2049
+ dateRange?: {
2050
+ start: Date;
2051
+ end: Date;
2052
+ };
2053
+ }
2054
+ /**
2055
+ * Date range filter for analytics queries
2056
+ */
2057
+ interface AnalyticsDateRange {
2058
+ start: Date;
2059
+ end: Date;
2060
+ }
2061
+ /**
2062
+ * Common filters for analytics queries
2063
+ */
2064
+ interface AnalyticsFilters {
2065
+ clinicBranchId?: string;
2066
+ practitionerId?: string;
2067
+ procedureId?: string;
2068
+ patientId?: string;
2069
+ }
2070
+ /**
2071
+ * Grouping period for trend analysis
2072
+ */
2073
+ type GroupingPeriod = 'day' | 'week' | 'month';
2074
+ /**
2075
+ * Entity type for grouping analytics
2076
+ */
2077
+ type EntityType = 'clinic' | 'practitioner' | 'patient' | 'procedure' | 'technology';
2078
+ /**
2079
+ * Practitioner Analytics
2080
+ * Comprehensive metrics for a practitioner's performance
2081
+ */
2082
+ interface PractitionerAnalytics extends BaseMetrics {
2083
+ practitionerId: string;
2084
+ practitionerName: string;
2085
+ totalAppointments: number;
2086
+ completedAppointments: number;
2087
+ canceledAppointments: number;
2088
+ noShowAppointments: number;
2089
+ pendingAppointments: number;
2090
+ confirmedAppointments: number;
2091
+ cancellationRate: number;
2092
+ noShowRate: number;
2093
+ averageBookedTime: number;
2094
+ averageActualTime: number;
2095
+ timeEfficiency: number;
2096
+ totalRevenue: number;
2097
+ averageRevenuePerAppointment: number;
2098
+ currency: string;
2099
+ topProcedures: Array<{
2100
+ procedureId: string;
2101
+ procedureName: string;
2102
+ count: number;
2103
+ revenue: number;
2104
+ }>;
2105
+ patientRetentionRate: number;
2106
+ uniquePatients: number;
2107
+ }
2108
+ /**
2109
+ * Procedure Analytics
2110
+ * Comprehensive metrics for procedure performance
2111
+ */
2112
+ interface ProcedureAnalytics extends BaseMetrics {
2113
+ procedureId: string;
2114
+ procedureName: string;
2115
+ procedureFamily: string;
2116
+ categoryName: string;
2117
+ subcategoryName: string;
2118
+ technologyName: string;
2119
+ totalAppointments: number;
2120
+ completedAppointments: number;
2121
+ canceledAppointments: number;
2122
+ noShowAppointments: number;
2123
+ cancellationRate: number;
2124
+ noShowRate: number;
2125
+ averageCost: number;
2126
+ totalRevenue: number;
2127
+ averageRevenuePerAppointment: number;
2128
+ currency: string;
2129
+ averageBookedDuration: number;
2130
+ averageActualDuration: number;
2131
+ productUsage: Array<{
2132
+ productId: string;
2133
+ productName: string;
2134
+ brandName: string;
2135
+ totalQuantity: number;
2136
+ totalRevenue: number;
2137
+ usageCount: number;
2138
+ }>;
2139
+ }
2140
+ /**
2141
+ * Time Efficiency Metrics
2142
+ * Analysis of booked time vs actual time spent
2143
+ */
2144
+ interface TimeEfficiencyMetrics {
2145
+ totalAppointments: number;
2146
+ appointmentsWithActualTime: number;
2147
+ averageBookedDuration: number;
2148
+ averageActualDuration: number;
2149
+ averageEfficiency: number;
2150
+ totalOverrun: number;
2151
+ totalUnderutilization: number;
2152
+ averageOverrun: number;
2153
+ averageUnderutilization: number;
2154
+ efficiencyDistribution: Array<{
2155
+ range: string;
2156
+ count: number;
2157
+ percentage: number;
2158
+ }>;
2159
+ }
2160
+ /**
2161
+ * Cancellation Metrics
2162
+ * Analysis of appointment cancellations
2163
+ */
2164
+ interface CancellationMetrics {
2165
+ entityId: string;
2166
+ entityName: string;
2167
+ entityType: EntityType;
2168
+ totalAppointments: number;
2169
+ canceledAppointments: number;
2170
+ cancellationRate: number;
2171
+ canceledByPatient: number;
2172
+ canceledByClinic: number;
2173
+ canceledByPractitioner: number;
2174
+ canceledRescheduled: number;
2175
+ averageCancellationLeadTime: number;
2176
+ cancellationReasons: Array<{
2177
+ reason: string;
2178
+ count: number;
2179
+ percentage: number;
2180
+ }>;
2181
+ }
2182
+ /**
2183
+ * No-Show Metrics
2184
+ * Analysis of appointment no-shows
2185
+ */
2186
+ interface NoShowMetrics {
2187
+ entityId: string;
2188
+ entityName: string;
2189
+ entityType: EntityType;
2190
+ totalAppointments: number;
2191
+ noShowAppointments: number;
2192
+ noShowRate: number;
2193
+ }
2194
+ /**
2195
+ * Revenue Metrics
2196
+ * Financial analysis and revenue tracking
2197
+ */
2198
+ interface RevenueMetrics {
2199
+ totalRevenue: number;
2200
+ averageRevenuePerAppointment: number;
2201
+ totalAppointments: number;
2202
+ completedAppointments: number;
2203
+ currency: string;
2204
+ revenueByStatus: Partial<Record<AppointmentStatus, number>>;
2205
+ revenueByPaymentStatus: Partial<Record<PaymentStatus, number>>;
2206
+ unpaidRevenue: number;
2207
+ refundedRevenue: number;
2208
+ totalTax: number;
2209
+ totalSubtotal: number;
2210
+ }
2211
+ /**
2212
+ * Revenue Trend
2213
+ * Revenue data over time
2214
+ */
2215
+ interface RevenueTrend {
2216
+ period: string;
2217
+ startDate: Date;
2218
+ endDate: Date;
2219
+ revenue: number;
2220
+ appointmentCount: number;
2221
+ averageRevenue: number;
2222
+ }
2223
+ /**
2224
+ * Duration Trend
2225
+ * Appointment duration trends over time
2226
+ */
2227
+ interface DurationTrend {
2228
+ period: string;
2229
+ startDate: Date;
2230
+ endDate: Date;
2231
+ averageBookedDuration: number;
2232
+ averageActualDuration: number;
2233
+ averageEfficiency: number;
2234
+ appointmentCount: number;
2235
+ }
2236
+ /**
2237
+ * Product Usage Metrics
2238
+ * Analysis of product usage in appointments
2239
+ */
2240
+ interface ProductUsageMetrics {
2241
+ productId: string;
2242
+ productName: string;
2243
+ brandId: string;
2244
+ brandName: string;
2245
+ totalQuantity: number;
2246
+ totalRevenue: number;
2247
+ averagePrice: number;
2248
+ currency: string;
2249
+ usageCount: number;
2250
+ averageQuantityPerAppointment: number;
2251
+ usageByProcedure: Array<{
2252
+ procedureId: string;
2253
+ procedureName: string;
2254
+ count: number;
2255
+ totalQuantity: number;
2256
+ }>;
2257
+ }
2258
+ /**
2259
+ * Product Revenue Metrics
2260
+ * Revenue contribution by product
2261
+ */
2262
+ interface ProductRevenueMetrics {
2263
+ productId: string;
2264
+ productName: string;
2265
+ brandName: string;
2266
+ totalRevenue: number;
2267
+ currency: string;
2268
+ usageCount: number;
2269
+ averageRevenuePerUsage: number;
2270
+ }
2271
+ /**
2272
+ * Product Usage by Procedure
2273
+ * Product usage patterns for specific procedures
2274
+ */
2275
+ interface ProductUsageByProcedure {
2276
+ procedureId: string;
2277
+ procedureName: string;
2278
+ products: Array<{
2279
+ productId: string;
2280
+ productName: string;
2281
+ brandName: string;
2282
+ totalQuantity: number;
2283
+ totalRevenue: number;
2284
+ usageCount: number;
2285
+ }>;
2286
+ }
2287
+ /**
2288
+ * Patient Analytics
2289
+ * Comprehensive patient metrics
2290
+ */
2291
+ interface PatientAnalytics {
2292
+ patientId: string;
2293
+ patientName: string;
2294
+ totalAppointments: number;
2295
+ completedAppointments: number;
2296
+ canceledAppointments: number;
2297
+ noShowAppointments: number;
2298
+ cancellationRate: number;
2299
+ noShowRate: number;
2300
+ totalRevenue: number;
2301
+ averageRevenuePerAppointment: number;
2302
+ currency: string;
2303
+ lifetimeValue: number;
2304
+ firstAppointmentDate: Date | null;
2305
+ lastAppointmentDate: Date | null;
2306
+ averageDaysBetweenAppointments: number | null;
2307
+ uniquePractitioners: number;
2308
+ uniqueClinics: number;
2309
+ favoriteProcedures: Array<{
2310
+ procedureId: string;
2311
+ procedureName: string;
2312
+ count: number;
2313
+ }>;
2314
+ }
2315
+ /**
2316
+ * Patient Lifetime Value Metrics
2317
+ * Patient value analysis
2318
+ */
2319
+ interface PatientLifetimeValueMetrics {
2320
+ totalPatients: number;
2321
+ averageLifetimeValue: number;
2322
+ currency: string;
2323
+ topPatients: Array<{
2324
+ patientId: string;
2325
+ patientName: string;
2326
+ lifetimeValue: number;
2327
+ appointmentCount: number;
2328
+ }>;
2329
+ valueDistribution: Array<{
2330
+ range: string;
2331
+ count: number;
2332
+ percentage: number;
2333
+ }>;
2334
+ }
2335
+ /**
2336
+ * Patient Retention Metrics
2337
+ * Patient retention and return analysis
2338
+ */
2339
+ interface PatientRetentionMetrics {
2340
+ totalPatients: number;
2341
+ newPatients: number;
2342
+ returningPatients: number;
2343
+ retentionRate: number;
2344
+ averageAppointmentsPerPatient: number;
2345
+ patientsByAppointmentCount: Array<{
2346
+ appointmentCount: number;
2347
+ patientCount: number;
2348
+ percentage: number;
2349
+ }>;
2350
+ }
2351
+ /**
2352
+ * Cost Per Patient Metrics
2353
+ * Cost analysis per patient
2354
+ */
2355
+ interface CostPerPatientMetrics {
2356
+ totalPatients: number;
2357
+ totalRevenue: number;
2358
+ averageCostPerPatient: number;
2359
+ currency: string;
2360
+ costDistribution: Array<{
2361
+ range: string;
2362
+ patientCount: number;
2363
+ percentage: number;
2364
+ }>;
2365
+ patientCosts?: Array<{
2366
+ patientId: string;
2367
+ patientName: string;
2368
+ totalCost: number;
2369
+ appointmentCount: number;
2370
+ averageCost: number;
2371
+ }>;
2372
+ }
2373
+ /**
2374
+ * Payment Status Breakdown
2375
+ * Analysis of payment statuses
2376
+ */
2377
+ interface PaymentStatusBreakdown {
2378
+ totalAppointments: number;
2379
+ byStatus: Partial<Record<PaymentStatus, {
2380
+ count: number;
2381
+ percentage: number;
2382
+ totalRevenue: number;
2383
+ }>>;
2384
+ unpaidCount: number;
2385
+ unpaidRevenue: number;
2386
+ paidCount: number;
2387
+ paidRevenue: number;
2388
+ partiallyPaidCount: number;
2389
+ partiallyPaidRevenue: number;
2390
+ refundedCount: number;
2391
+ refundedRevenue: number;
2392
+ }
2393
+ /**
2394
+ * Clinic Analytics
2395
+ * Comprehensive clinic performance metrics
2396
+ */
2397
+ interface ClinicAnalytics {
2398
+ clinicBranchId: string;
2399
+ clinicName: string;
2400
+ totalAppointments: number;
2401
+ completedAppointments: number;
2402
+ canceledAppointments: number;
2403
+ noShowAppointments: number;
2404
+ cancellationRate: number;
2405
+ noShowRate: number;
2406
+ totalRevenue: number;
2407
+ averageRevenuePerAppointment: number;
2408
+ currency: string;
2409
+ practitionerCount: number;
2410
+ patientCount: number;
2411
+ procedureCount: number;
2412
+ topPractitioners: Array<{
2413
+ practitionerId: string;
2414
+ practitionerName: string;
2415
+ appointmentCount: number;
2416
+ revenue: number;
2417
+ }>;
2418
+ topProcedures: Array<{
2419
+ procedureId: string;
2420
+ procedureName: string;
2421
+ appointmentCount: number;
2422
+ revenue: number;
2423
+ }>;
2424
+ }
2425
+ /**
2426
+ * Clinic Comparison Metrics
2427
+ * Comparison data for multiple clinics
2428
+ */
2429
+ interface ClinicComparisonMetrics {
2430
+ clinicBranchId: string;
2431
+ clinicName: string;
2432
+ totalAppointments: number;
2433
+ completedAppointments: number;
2434
+ cancellationRate: number;
2435
+ noShowRate: number;
2436
+ totalRevenue: number;
2437
+ averageRevenuePerAppointment: number;
2438
+ practitionerCount: number;
2439
+ patientCount: number;
2440
+ efficiency: number;
2441
+ }
2442
+ /**
2443
+ * Procedure Popularity
2444
+ * Popularity metrics for procedures
2445
+ */
2446
+ interface ProcedurePopularity {
2447
+ procedureId: string;
2448
+ procedureName: string;
2449
+ categoryName: string;
2450
+ subcategoryName: string;
2451
+ technologyName: string;
2452
+ appointmentCount: number;
2453
+ completedCount: number;
2454
+ rank: number;
2455
+ }
2456
+ /**
2457
+ * Procedure Profitability
2458
+ * Profitability metrics for procedures
2459
+ */
2460
+ interface ProcedureProfitability {
2461
+ procedureId: string;
2462
+ procedureName: string;
2463
+ categoryName: string;
2464
+ subcategoryName: string;
2465
+ technologyName: string;
2466
+ totalRevenue: number;
2467
+ averageRevenue: number;
2468
+ appointmentCount: number;
2469
+ rank: number;
2470
+ }
2471
+ /**
2472
+ * Cancellation Reason Statistics
2473
+ * Breakdown of cancellation reasons
2474
+ */
2475
+ interface CancellationReasonStats {
2476
+ reason: string;
2477
+ count: number;
2478
+ percentage: number;
2479
+ averageLeadTime: number;
2480
+ }
2481
+ /**
2482
+ * Dashboard Analytics
2483
+ * Comprehensive dashboard data aggregation
2484
+ */
2485
+ interface DashboardAnalytics {
2486
+ overview: {
2487
+ totalAppointments: number;
2488
+ completedAppointments: number;
2489
+ canceledAppointments: number;
2490
+ noShowAppointments: number;
2491
+ pendingAppointments: number;
2492
+ confirmedAppointments: number;
2493
+ totalRevenue: number;
2494
+ averageRevenuePerAppointment: number;
2495
+ currency: string;
2496
+ uniquePatients: number;
2497
+ uniquePractitioners: number;
2498
+ uniqueProcedures: number;
2499
+ cancellationRate: number;
2500
+ noShowRate: number;
2501
+ };
2502
+ practitionerMetrics: PractitionerAnalytics[];
2503
+ procedureMetrics: ProcedureAnalytics[];
2504
+ cancellationMetrics: CancellationMetrics;
2505
+ noShowMetrics: NoShowMetrics;
2506
+ revenueTrends: RevenueTrend[];
2507
+ timeEfficiency: TimeEfficiencyMetrics;
2508
+ topProducts: ProductUsageMetrics[];
2509
+ recentActivity: Array<{
2510
+ type: 'appointment' | 'cancellation' | 'completion' | 'no_show';
2511
+ date: Date;
2512
+ description: string;
2513
+ entityId?: string;
2514
+ entityName?: string;
2515
+ }>;
2516
+ }
2517
+
2518
+ /**
2519
+ * Period type for analytics snapshots
2520
+ */
2521
+ type AnalyticsPeriod = 'daily' | 'weekly' | 'monthly' | 'yearly' | 'all_time';
2522
+ /**
2523
+ * Analytics document metadata
2524
+ */
2525
+ interface AnalyticsMetadata {
2526
+ clinicBranchId: string;
2527
+ period: AnalyticsPeriod;
2528
+ periodStart: Date;
2529
+ periodEnd: Date;
2530
+ computedAt: Timestamp;
2531
+ computedBy: 'cloud_function' | 'manual';
2532
+ version: string;
2533
+ }
2534
+ /**
2535
+ * Stored Practitioner Analytics
2536
+ * Stored in: clinics/{clinicBranchId}/analytics/practitioners/{practitionerId}/{period}
2537
+ */
2538
+ interface StoredPractitionerAnalytics extends PractitionerAnalytics {
2539
+ metadata: AnalyticsMetadata;
2540
+ }
2541
+ /**
2542
+ * Stored Procedure Analytics
2543
+ * Stored in: clinics/{clinicBranchId}/analytics/procedures/{procedureId}/{period}
2544
+ */
2545
+ interface StoredProcedureAnalytics extends ProcedureAnalytics {
2546
+ metadata: AnalyticsMetadata;
2547
+ }
2548
+ /**
2549
+ * Stored Clinic Analytics
2550
+ * Stored in: clinics/{clinicBranchId}/analytics/clinic/{period}
2551
+ */
2552
+ interface StoredClinicAnalytics extends ClinicAnalytics {
2553
+ metadata: AnalyticsMetadata;
2554
+ }
2555
+ /**
2556
+ * Stored Dashboard Analytics
2557
+ * Stored in: clinics/{clinicBranchId}/analytics/dashboard/{period}
2558
+ */
2559
+ interface StoredDashboardAnalytics extends DashboardAnalytics {
2560
+ metadata: AnalyticsMetadata;
2561
+ }
2562
+ /**
2563
+ * Stored Time Efficiency Metrics
2564
+ * Stored in: clinics/{clinicBranchId}/analytics/time_efficiency/{period}
2565
+ */
2566
+ interface StoredTimeEfficiencyMetrics extends TimeEfficiencyMetrics {
2567
+ metadata: AnalyticsMetadata;
2568
+ }
2569
+ /**
2570
+ * Stored Cancellation Metrics
2571
+ * Stored in: clinics/{clinicBranchId}/analytics/cancellations/{entityType}/{period}
2572
+ */
2573
+ interface StoredCancellationMetrics extends CancellationMetrics {
2574
+ metadata: AnalyticsMetadata;
2575
+ }
2576
+ /**
2577
+ * Stored No-Show Metrics
2578
+ * Stored in: clinics/{clinicBranchId}/analytics/no_shows/{entityType}/{period}
2579
+ */
2580
+ interface StoredNoShowMetrics extends NoShowMetrics {
2581
+ metadata: AnalyticsMetadata;
2582
+ }
2583
+ /**
2584
+ * Stored Revenue Metrics
2585
+ * Stored in: clinics/{clinicBranchId}/analytics/revenue/{period}
2586
+ */
2587
+ interface StoredRevenueMetrics extends RevenueMetrics {
2588
+ metadata: AnalyticsMetadata;
2589
+ }
2590
+ /**
2591
+ * Collection names for stored analytics
2592
+ */
2593
+ declare const ANALYTICS_COLLECTION = "analytics";
2594
+ declare const PRACTITIONER_ANALYTICS_SUBCOLLECTION = "practitioners";
2595
+ declare const PROCEDURE_ANALYTICS_SUBCOLLECTION = "procedures";
2596
+ declare const CLINIC_ANALYTICS_SUBCOLLECTION = "clinic";
2597
+ declare const DASHBOARD_ANALYTICS_SUBCOLLECTION = "dashboard";
2598
+ declare const TIME_EFFICIENCY_ANALYTICS_SUBCOLLECTION = "time_efficiency";
2599
+ declare const CANCELLATION_ANALYTICS_SUBCOLLECTION = "cancellations";
2600
+ declare const NO_SHOW_ANALYTICS_SUBCOLLECTION = "no_shows";
2601
+ declare const REVENUE_ANALYTICS_SUBCOLLECTION = "revenue";
2602
+ /**
2603
+ * Options for reading stored analytics
2604
+ */
2605
+ interface ReadStoredAnalyticsOptions {
2606
+ /**
2607
+ * Whether to use cached/pre-computed data
2608
+ * @default true
2609
+ */
2610
+ useCache?: boolean;
2611
+ /**
2612
+ * Maximum age of cached data in hours before recalculating
2613
+ * @default 12
2614
+ */
2615
+ maxCacheAgeHours?: number;
2616
+ /**
2617
+ * Period to read
2618
+ * @default 'all_time'
2619
+ */
2620
+ period?: AnalyticsPeriod;
2621
+ /**
2622
+ * Date range for the period (calculated if not provided)
2623
+ */
2624
+ dateRange?: AnalyticsDateRange;
2625
+ /**
2626
+ * Clinic branch ID (required for reading stored analytics)
2627
+ */
2628
+ clinicBranchId?: string;
2629
+ }
2630
+
2631
+ /**
2632
+ * Base interface for grouped analytics results
2633
+ * All grouped analytics share common entity identification
2634
+ */
2635
+ interface GroupedAnalyticsBase {
2636
+ entityId: string;
2637
+ entityName: string;
2638
+ entityType: EntityType;
2639
+ }
2640
+ /**
2641
+ * Grouped Revenue Metrics
2642
+ * Revenue analytics grouped by clinic, practitioner, procedure, or patient
2643
+ */
2644
+ interface GroupedRevenueMetrics extends GroupedAnalyticsBase {
2645
+ totalRevenue: number;
2646
+ averageRevenuePerAppointment: number;
2647
+ totalAppointments: number;
2648
+ completedAppointments: number;
2649
+ currency: string;
2650
+ unpaidRevenue: number;
2651
+ refundedRevenue: number;
2652
+ totalTax: number;
2653
+ totalSubtotal: number;
2654
+ }
2655
+ /**
2656
+ * Grouped Product Usage Metrics
2657
+ * Product usage analytics grouped by clinic, practitioner, procedure, or patient
2658
+ */
2659
+ interface GroupedProductUsageMetrics extends GroupedAnalyticsBase {
2660
+ totalProductsUsed: number;
2661
+ uniqueProducts: number;
2662
+ totalProductRevenue: number;
2663
+ totalProductQuantity: number;
2664
+ averageProductsPerAppointment: number;
2665
+ topProducts: Array<{
2666
+ productId: string;
2667
+ productName: string;
2668
+ brandName: string;
2669
+ totalQuantity: number;
2670
+ totalRevenue: number;
2671
+ usageCount: number;
2672
+ }>;
2673
+ }
2674
+ /**
2675
+ * Grouped Patient Retention Metrics
2676
+ * Patient retention analytics grouped by clinic, practitioner, or procedure
2677
+ */
2678
+ interface GroupedPatientRetentionMetrics extends GroupedAnalyticsBase {
2679
+ totalPatients: number;
2680
+ newPatients: number;
2681
+ returningPatients: number;
2682
+ retentionRate: number;
2683
+ averageAppointmentsPerPatient: number;
2684
+ patientsByAppointmentCount: Array<{
2685
+ appointmentCount: number;
2686
+ patientCount: number;
2687
+ percentage: number;
2688
+ }>;
2689
+ }
2690
+ /**
2691
+ * Grouped Time Efficiency Metrics
2692
+ * Time efficiency analytics grouped by clinic, practitioner, procedure, or patient
2693
+ */
2694
+ interface GroupedTimeEfficiencyMetrics extends GroupedAnalyticsBase {
2695
+ totalAppointments: number;
2696
+ appointmentsWithActualTime: number;
2697
+ averageBookedDuration: number;
2698
+ averageActualDuration: number;
2699
+ averageEfficiency: number;
2700
+ totalOverrun: number;
2701
+ totalUnderutilization: number;
2702
+ averageOverrun: number;
2703
+ averageUnderutilization: number;
2704
+ }
2705
+ /**
2706
+ * Grouped Patient Behavior Metrics
2707
+ * Patient behavior (no-show, cancellation) grouped by clinic, practitioner, or procedure
2708
+ */
2709
+ interface GroupedPatientBehaviorMetrics extends GroupedAnalyticsBase {
2710
+ totalPatients: number;
2711
+ patientsWithNoShows: number;
2712
+ patientsWithCancellations: number;
2713
+ averageNoShowRate: number;
2714
+ averageCancellationRate: number;
2715
+ topNoShowPatients: Array<{
2716
+ patientId: string;
2717
+ patientName: string;
2718
+ noShowCount: number;
2719
+ totalAppointments: number;
2720
+ noShowRate: number;
2721
+ }>;
2722
+ topCancellationPatients: Array<{
2723
+ patientId: string;
2724
+ patientName: string;
2725
+ cancellationCount: number;
2726
+ totalAppointments: number;
2727
+ cancellationRate: number;
2728
+ }>;
2729
+ }
2730
+ /**
2731
+ * Grouped Procedure Performance Metrics
2732
+ * Procedure performance grouped by clinic or practitioner
2733
+ */
2734
+ interface GroupedProcedurePerformanceMetrics extends GroupedAnalyticsBase {
2735
+ totalProcedures: number;
2736
+ totalAppointments: number;
2737
+ completedAppointments: number;
2738
+ totalRevenue: number;
2739
+ averageRevenuePerProcedure: number;
2740
+ topProcedures: Array<{
2741
+ procedureId: string;
2742
+ procedureName: string;
2743
+ appointmentCount: number;
2744
+ revenue: number;
2745
+ cancellationRate: number;
2746
+ noShowRate: number;
2747
+ }>;
2748
+ }
2749
+ /**
2750
+ * Grouped Practitioner Performance Metrics
2751
+ * Practitioner performance grouped by clinic
2752
+ */
2753
+ interface GroupedPractitionerPerformanceMetrics extends GroupedAnalyticsBase {
2754
+ totalPractitioners: number;
2755
+ totalAppointments: number;
2756
+ completedAppointments: number;
2757
+ totalRevenue: number;
2758
+ averageRevenuePerPractitioner: number;
2759
+ topPractitioners: Array<{
2760
+ practitionerId: string;
2761
+ practitionerName: string;
2762
+ appointmentCount: number;
2763
+ revenue: number;
2764
+ cancellationRate: number;
2765
+ noShowRate: number;
2766
+ timeEfficiency: number;
2767
+ }>;
2768
+ }
2769
+
2042
2770
  /**
2043
2771
  * Enumeracija koja definiše sve moguće tipove notifikacija
2044
2772
  */
@@ -2053,6 +2781,7 @@ declare enum NotificationType {
2053
2781
  FORM_REMINDER = "formReminder",// Reminds user to fill a specific form
2054
2782
  FORM_SUBMISSION_CONFIRMATION = "formSubmissionConfirmation",// Confirms form was submitted
2055
2783
  REVIEW_REQUEST = "reviewRequest",// Request for patient review post-appointment
2784
+ PROCEDURE_RECOMMENDATION = "procedureRecommendation",// Doctor recommended a procedure for follow-up
2056
2785
  PAYMENT_DUE = "paymentDue",
2057
2786
  PAYMENT_CONFIRMATION = "paymentConfirmation",
2058
2787
  PAYMENT_FAILED = "paymentFailed",
@@ -2222,6 +2951,24 @@ interface ReviewRequestNotification extends BaseNotification {
2222
2951
  practitionerName?: string;
2223
2952
  procedureName?: string;
2224
2953
  }
2954
+ /**
2955
+ * Notification for when a doctor recommends a procedure for follow-up.
2956
+ * Example: "Dr. Smith recommended [Procedure Name] for you. Suggested timeframe: in 2 weeks"
2957
+ */
2958
+ interface ProcedureRecommendationNotification extends BaseNotification {
2959
+ notificationType: NotificationType.PROCEDURE_RECOMMENDATION;
2960
+ appointmentId: string;
2961
+ recommendationId: string;
2962
+ procedureId: string;
2963
+ procedureName: string;
2964
+ practitionerName: string;
2965
+ clinicName: string;
2966
+ note?: string;
2967
+ timeframe: {
2968
+ value: number;
2969
+ unit: 'day' | 'week' | 'month' | 'year';
2970
+ };
2971
+ }
2225
2972
  /**
2226
2973
  * Generic notification for direct messages or announcements.
2227
2974
  */
@@ -2237,7 +2984,7 @@ interface PaymentConfirmationNotification extends BaseNotification {
2237
2984
  /**
2238
2985
  * Unija svih tipova notifikacija
2239
2986
  */
2240
- type Notification = PreRequirementNotification | PostRequirementNotification | RequirementInstructionDueNotification | AppointmentReminderNotification | AppointmentStatusChangeNotification | AppointmentRescheduledProposalNotification | AppointmentCancelledNotification | FormReminderNotification | FormSubmissionConfirmationNotification | ReviewRequestNotification | GeneralMessageNotification | PaymentConfirmationNotification;
2987
+ type Notification = PreRequirementNotification | PostRequirementNotification | RequirementInstructionDueNotification | AppointmentReminderNotification | AppointmentStatusChangeNotification | AppointmentRescheduledProposalNotification | AppointmentCancelledNotification | FormReminderNotification | FormSubmissionConfirmationNotification | ReviewRequestNotification | ProcedureRecommendationNotification | GeneralMessageNotification | PaymentConfirmationNotification;
2241
2988
 
2242
2989
  /**
2243
2990
  * Minimal interface for the new mailgun.js client's messages API
@@ -2676,6 +3423,20 @@ declare class AppointmentAggregationService {
2676
3423
  * @param after - The appointment state after update
2677
3424
  */
2678
3425
  private handleZonePhotosUpdate;
3426
+ /**
3427
+ * Checks if recommended procedures have changed between two appointment states
3428
+ * @param before - The appointment state before update
3429
+ * @param after - The appointment state after update
3430
+ * @returns True if recommendations have changed, false otherwise
3431
+ */
3432
+ private hasRecommendationsChanged;
3433
+ /**
3434
+ * Handles recommended procedures update - creates notifications for newly added recommendations
3435
+ * @param before - The appointment state before update
3436
+ * @param after - The appointment state after update
3437
+ * @param patientProfile - The patient profile (for expo tokens)
3438
+ */
3439
+ private handleRecommendedProceduresUpdate;
2679
3440
  }
2680
3441
 
2681
3442
  /**
@@ -3175,6 +3936,44 @@ declare class ReviewsAggregationService {
3175
3936
  calculateEntityReviewInfo(entityId: string, entityType: "clinic" | "practitioner" | "procedure"): Promise<ClinicReviewInfo | PractitionerReviewInfo | ProcedureReviewInfo>;
3176
3937
  }
3177
3938
 
3939
+ /**
3940
+ * Admin version of AnalyticsService that uses Firebase Admin SDK
3941
+ * This is intended for use in Cloud Functions and server-side code
3942
+ */
3943
+ declare class AnalyticsAdminService {
3944
+ private analyticsService;
3945
+ private db;
3946
+ /**
3947
+ * Creates a new AnalyticsAdminService instance
3948
+ *
3949
+ * @param firestore - Admin Firestore instance (optional, defaults to admin.firestore())
3950
+ */
3951
+ constructor(firestore?: admin.firestore.Firestore);
3952
+ /**
3953
+ * Creates an adapter for AppointmentService to work with admin SDK
3954
+ */
3955
+ private createAppointmentServiceAdapter;
3956
+ getPractitionerAnalytics(practitionerId: string, dateRange?: AnalyticsDateRange, options?: any): Promise<PractitionerAnalytics>;
3957
+ getProcedureAnalytics(procedureId?: string, dateRange?: AnalyticsDateRange, options?: any): Promise<ProcedureAnalytics | ProcedureAnalytics[]>;
3958
+ getTimeEfficiencyMetrics(filters?: AnalyticsFilters, dateRange?: AnalyticsDateRange, options?: any): Promise<TimeEfficiencyMetrics>;
3959
+ getTimeEfficiencyMetricsByEntity(groupBy: EntityType, dateRange?: AnalyticsDateRange, filters?: AnalyticsFilters): Promise<GroupedTimeEfficiencyMetrics[]>;
3960
+ getCancellationMetrics(groupBy: EntityType, dateRange?: AnalyticsDateRange, options?: any): Promise<CancellationMetrics | CancellationMetrics[]>;
3961
+ getNoShowMetrics(groupBy: EntityType, dateRange?: AnalyticsDateRange, options?: any): Promise<NoShowMetrics | NoShowMetrics[]>;
3962
+ getRevenueMetrics(filters?: AnalyticsFilters, dateRange?: AnalyticsDateRange, options?: any): Promise<RevenueMetrics>;
3963
+ getRevenueMetricsByEntity(groupBy: EntityType, dateRange?: AnalyticsDateRange, filters?: AnalyticsFilters): Promise<GroupedRevenueMetrics[]>;
3964
+ getProductUsageMetrics(productId?: string, dateRange?: AnalyticsDateRange): Promise<ProductUsageMetrics | ProductUsageMetrics[]>;
3965
+ getProductUsageMetricsByEntity(groupBy: EntityType, dateRange?: AnalyticsDateRange, filters?: AnalyticsFilters): Promise<GroupedProductUsageMetrics[]>;
3966
+ getPatientAnalytics(patientId?: string, dateRange?: AnalyticsDateRange): Promise<PatientAnalytics | PatientAnalytics[]>;
3967
+ getPatientBehaviorMetricsByEntity(groupBy: 'clinic' | 'practitioner' | 'procedure' | 'technology', dateRange?: AnalyticsDateRange, filters?: AnalyticsFilters): Promise<GroupedPatientBehaviorMetrics[]>;
3968
+ getClinicAnalytics(clinicBranchId: string, dateRange?: AnalyticsDateRange): Promise<ClinicAnalytics | ClinicAnalytics[]>;
3969
+ getDashboardData(filters?: AnalyticsFilters, dateRange?: AnalyticsDateRange, options?: any): Promise<DashboardAnalytics>;
3970
+ /**
3971
+ * Expose fetchAppointments for direct access if needed
3972
+ * This method is used internally by AnalyticsService
3973
+ */
3974
+ fetchAppointments(filters?: AnalyticsFilters, dateRange?: AnalyticsDateRange): Promise<any[]>;
3975
+ }
3976
+
3178
3977
  /**
3179
3978
  * Request parameters for calculating available booking slots
3180
3979
  */
@@ -3766,4 +4565,4 @@ declare class UserProfileAdminService {
3766
4565
  initializePractitionerRole(userId: string): Promise<User>;
3767
4566
  }
3768
4567
 
3769
- export { type Appointment, AppointmentAggregationService, type AppointmentCancellationEmailData, type AppointmentConfirmationEmailData, type AppointmentEmailDataBase, AppointmentMailingService, type AppointmentReminderNotification, type AppointmentRequestedEmailData, type AppointmentRescheduledProposalEmailData, AppointmentStatus, type AvailableSlot, BaseMailingService, type BaseNotification, type BillingInfo, type BillingTransaction, BillingTransactionType, BookingAdmin, BookingAvailabilityCalculator, type BookingAvailabilityRequest, type BookingAvailabilityResponse, CalendarAdminService, type Clinic, type ClinicAdminNotificationData, ClinicAggregationService, type ClinicInfo, type ClinicLocation, type CreateBillingTransactionData, type DoctorInfo, DocumentManagerAdminService, type ExistingPractitionerInviteEmailData, ExistingPractitionerInviteMailingService, type FilledDocument, FilledFormsAggregationService, type InitializeAppointmentFormsResult, Logger, NOTIFICATIONS_COLLECTION, type NewMailgunClient$2 as NewMailgunClient, type Notification, NotificationStatus, NotificationType, NotificationsAdmin, type OrchestrateAppointmentCreationData, PATIENTS_COLLECTION, PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME, PATIENT_SENSITIVE_INFO_COLLECTION, type PatientProfile as Patient, PatientAggregationService, PatientInstructionStatus, type PatientProfile, type PatientRequirementInstance, type PatientRequirementInstruction, PatientRequirementOverallStatus, PatientRequirementsAdminService, type PatientSensitiveInfo, type PlanDetails, type PostRequirementNotification, type Practitioner, PractitionerAggregationService, type PractitionerInvite, PractitionerInviteAggregationService, type PractitionerInviteEmailData, PractitionerInviteMailingService, PractitionerInviteStatus, type PractitionerToken, PractitionerTokenStatus, type PreRequirementNotification, type Procedure, ProcedureAggregationService, type ProcedureSummaryInfo, type RequirementSourceProcedure, type Review, type ReviewAddedEmailData, type ReviewRequestEmailData, ReviewsAggregationService, type StripeTransactionData, SubscriptionStatus, type TimeInterval, UserProfileAdminService, UserRole, freeConsultationInfrastructure };
4568
+ export { ANALYTICS_COLLECTION, AnalyticsAdminService, type AnalyticsDateRange, type AnalyticsFilters, type AnalyticsMetadata, type AnalyticsPeriod, type Appointment, AppointmentAggregationService, type AppointmentCancellationEmailData, type AppointmentConfirmationEmailData, type AppointmentEmailDataBase, AppointmentMailingService, type AppointmentReminderNotification, type AppointmentRequestedEmailData, type AppointmentRescheduledProposalEmailData, AppointmentStatus, type AvailableSlot, BaseMailingService, type BaseMetrics, type BaseNotification, type BillingInfo, type BillingTransaction, BillingTransactionType, BookingAdmin, BookingAvailabilityCalculator, type BookingAvailabilityRequest, type BookingAvailabilityResponse, CANCELLATION_ANALYTICS_SUBCOLLECTION, CLINICS_COLLECTION, CLINIC_ANALYTICS_SUBCOLLECTION, CalendarAdminService, type CancellationMetrics, type CancellationReasonStats, type Clinic, type ClinicAdminNotificationData, ClinicAggregationService, type ClinicAnalytics, type ClinicComparisonMetrics, type ClinicInfo, type ClinicLocation, type CostPerPatientMetrics, type CreateBillingTransactionData, DASHBOARD_ANALYTICS_SUBCOLLECTION, type DashboardAnalytics, type DoctorInfo, DocumentManagerAdminService, type DurationTrend, type EntityType, type ExistingPractitionerInviteEmailData, ExistingPractitionerInviteMailingService, type FilledDocument, FilledFormsAggregationService, type GroupedAnalyticsBase, type GroupedPatientBehaviorMetrics, type GroupedPatientRetentionMetrics, type GroupedPractitionerPerformanceMetrics, type GroupedProcedurePerformanceMetrics, type GroupedProductUsageMetrics, type GroupedRevenueMetrics, type GroupedTimeEfficiencyMetrics, type GroupingPeriod, type InitializeAppointmentFormsResult, Logger, NOTIFICATIONS_COLLECTION, NO_SHOW_ANALYTICS_SUBCOLLECTION, type NewMailgunClient$2 as NewMailgunClient, type NoShowMetrics, type Notification, NotificationStatus, NotificationType, NotificationsAdmin, type OrchestrateAppointmentCreationData, PATIENTS_COLLECTION, PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME, PATIENT_SENSITIVE_INFO_COLLECTION, PRACTITIONER_ANALYTICS_SUBCOLLECTION, PROCEDURE_ANALYTICS_SUBCOLLECTION, type PatientProfile as Patient, PatientAggregationService, type PatientAnalytics, PatientInstructionStatus, type PatientLifetimeValueMetrics, type PatientProfile, type PatientRequirementInstance, type PatientRequirementInstruction, PatientRequirementOverallStatus, PatientRequirementsAdminService, type PatientRetentionMetrics, type PatientSensitiveInfo, type PaymentStatusBreakdown, type PlanDetails, type PostRequirementNotification, type Practitioner, PractitionerAggregationService, type PractitionerAnalytics, type PractitionerInvite, PractitionerInviteAggregationService, type PractitionerInviteEmailData, PractitionerInviteMailingService, PractitionerInviteStatus, type PractitionerToken, PractitionerTokenStatus, type PreRequirementNotification, type Procedure, ProcedureAggregationService, type ProcedureAnalytics, type ProcedurePopularity, type ProcedureProfitability, type ProcedureSummaryInfo, type ProductRevenueMetrics, type ProductUsageByProcedure, type ProductUsageMetrics, REVENUE_ANALYTICS_SUBCOLLECTION, type ReadStoredAnalyticsOptions, type RequirementSourceProcedure, type RevenueMetrics, type RevenueTrend, type Review, type ReviewAddedEmailData, type ReviewRequestEmailData, ReviewsAggregationService, type StoredCancellationMetrics, type StoredClinicAnalytics, type StoredDashboardAnalytics, type StoredNoShowMetrics, type StoredPractitionerAnalytics, type StoredProcedureAnalytics, type StoredRevenueMetrics, type StoredTimeEfficiencyMetrics, type StripeTransactionData, SubscriptionStatus, TIME_EFFICIENCY_ANALYTICS_SUBCOLLECTION, type TimeEfficiencyMetrics, type TimeInterval, UserProfileAdminService, UserRole, freeConsultationInfrastructure };