@blackcode_sa/metaestetics-api 1.13.4 → 1.13.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/index.d.mts +15 -28
- package/dist/admin/index.d.ts +15 -28
- package/dist/index.d.mts +16 -29
- package/dist/index.d.ts +16 -29
- package/dist/index.js +1 -0
- package/dist/index.mjs +1 -0
- package/package.json +121 -119
- package/src/__mocks__/firstore.ts +10 -10
- package/src/admin/aggregation/README.md +79 -79
- package/src/admin/aggregation/appointment/README.md +128 -128
- package/src/admin/aggregation/appointment/appointment.aggregation.service.ts +1984 -1984
- package/src/admin/aggregation/appointment/index.ts +1 -1
- package/src/admin/aggregation/clinic/README.md +52 -52
- package/src/admin/aggregation/clinic/clinic.aggregation.service.ts +703 -703
- package/src/admin/aggregation/clinic/index.ts +1 -1
- package/src/admin/aggregation/forms/README.md +13 -13
- package/src/admin/aggregation/forms/filled-forms.aggregation.service.ts +322 -322
- package/src/admin/aggregation/forms/index.ts +1 -1
- package/src/admin/aggregation/index.ts +8 -8
- package/src/admin/aggregation/patient/README.md +27 -27
- package/src/admin/aggregation/patient/index.ts +1 -1
- package/src/admin/aggregation/patient/patient.aggregation.service.ts +141 -141
- package/src/admin/aggregation/practitioner/README.md +42 -42
- package/src/admin/aggregation/practitioner/index.ts +1 -1
- package/src/admin/aggregation/practitioner/practitioner.aggregation.service.ts +433 -433
- package/src/admin/aggregation/practitioner-invite/index.ts +1 -1
- package/src/admin/aggregation/practitioner-invite/practitioner-invite.aggregation.service.ts +961 -961
- package/src/admin/aggregation/procedure/README.md +43 -43
- package/src/admin/aggregation/procedure/index.ts +1 -1
- package/src/admin/aggregation/procedure/procedure.aggregation.service.ts +702 -702
- package/src/admin/aggregation/reviews/index.ts +1 -1
- package/src/admin/aggregation/reviews/reviews.aggregation.service.ts +689 -689
- package/src/admin/analytics/analytics.admin.service.ts +278 -278
- package/src/admin/analytics/index.ts +2 -2
- package/src/admin/booking/README.md +125 -125
- package/src/admin/booking/booking.admin.ts +1037 -1037
- package/src/admin/booking/booking.calculator.ts +712 -712
- package/src/admin/booking/booking.types.ts +59 -59
- package/src/admin/booking/index.ts +3 -3
- package/src/admin/booking/timezones-problem.md +185 -185
- package/src/admin/calendar/README.md +7 -7
- package/src/admin/calendar/calendar.admin.service.ts +345 -345
- package/src/admin/calendar/index.ts +1 -1
- package/src/admin/documentation-templates/document-manager.admin.ts +260 -260
- package/src/admin/documentation-templates/index.ts +1 -1
- package/src/admin/free-consultation/free-consultation-utils.admin.ts +148 -148
- package/src/admin/free-consultation/index.ts +1 -1
- package/src/admin/index.ts +81 -81
- package/src/admin/logger/index.ts +78 -78
- package/src/admin/mailing/README.md +95 -95
- package/src/admin/mailing/appointment/appointment.mailing.service.ts +732 -732
- package/src/admin/mailing/appointment/index.ts +1 -1
- package/src/admin/mailing/appointment/templates/patient/appointment-confirmed.html +40 -40
- package/src/admin/mailing/base.mailing.service.ts +208 -208
- package/src/admin/mailing/index.ts +3 -3
- package/src/admin/mailing/practitionerInvite/existing-practitioner-invite.mailing.ts +611 -611
- package/src/admin/mailing/practitionerInvite/index.ts +2 -2
- package/src/admin/mailing/practitionerInvite/practitionerInvite.mailing.ts +395 -395
- package/src/admin/mailing/practitionerInvite/templates/existing-practitioner-invitation.template.ts +155 -155
- package/src/admin/mailing/practitionerInvite/templates/invitation.template.ts +101 -101
- package/src/admin/mailing/practitionerInvite/templates/invite-accepted-notification.template.ts +228 -228
- package/src/admin/mailing/practitionerInvite/templates/invite-rejected-notification.template.ts +242 -242
- package/src/admin/notifications/index.ts +1 -1
- package/src/admin/notifications/notifications.admin.ts +710 -710
- package/src/admin/requirements/README.md +128 -128
- package/src/admin/requirements/index.ts +1 -1
- package/src/admin/requirements/patient-requirements.admin.service.ts +475 -475
- package/src/admin/users/index.ts +1 -1
- package/src/admin/users/user-profile.admin.ts +405 -405
- package/src/backoffice/constants/certification.constants.ts +13 -13
- package/src/backoffice/constants/index.ts +1 -1
- package/src/backoffice/errors/backoffice.errors.ts +181 -181
- package/src/backoffice/errors/index.ts +1 -1
- package/src/backoffice/expo-safe/README.md +26 -26
- package/src/backoffice/expo-safe/index.ts +41 -41
- package/src/backoffice/index.ts +5 -5
- package/src/backoffice/services/FIXES_README.md +102 -102
- package/src/backoffice/services/README.md +57 -57
- package/src/backoffice/services/analytics.service.proposal.md +863 -863
- package/src/backoffice/services/analytics.service.summary.md +143 -143
- package/src/backoffice/services/brand.service.ts +256 -256
- package/src/backoffice/services/category.service.ts +384 -384
- package/src/backoffice/services/constants.service.ts +385 -385
- package/src/backoffice/services/documentation-template.service.ts +202 -202
- package/src/backoffice/services/index.ts +10 -10
- package/src/backoffice/services/migrate-products.ts +116 -116
- package/src/backoffice/services/product.service.ts +553 -553
- package/src/backoffice/services/requirement.service.ts +235 -235
- package/src/backoffice/services/subcategory.service.ts +461 -461
- package/src/backoffice/services/technology.service.ts +1151 -1151
- package/src/backoffice/types/README.md +12 -12
- package/src/backoffice/types/admin-constants.types.ts +69 -69
- package/src/backoffice/types/brand.types.ts +29 -29
- package/src/backoffice/types/category.types.ts +67 -67
- package/src/backoffice/types/documentation-templates.types.ts +28 -28
- package/src/backoffice/types/index.ts +10 -10
- package/src/backoffice/types/procedure-product.types.ts +38 -38
- package/src/backoffice/types/product.types.ts +240 -240
- package/src/backoffice/types/requirement.types.ts +63 -63
- package/src/backoffice/types/static/README.md +18 -18
- package/src/backoffice/types/static/blocking-condition.types.ts +21 -21
- package/src/backoffice/types/static/certification.types.ts +37 -37
- package/src/backoffice/types/static/contraindication.types.ts +19 -19
- package/src/backoffice/types/static/index.ts +6 -6
- package/src/backoffice/types/static/pricing.types.ts +16 -16
- package/src/backoffice/types/static/procedure-family.types.ts +14 -14
- package/src/backoffice/types/static/treatment-benefit.types.ts +22 -22
- package/src/backoffice/types/subcategory.types.ts +34 -34
- package/src/backoffice/types/technology.types.ts +168 -168
- package/src/backoffice/validations/index.ts +1 -1
- package/src/backoffice/validations/schemas.ts +164 -164
- package/src/config/__mocks__/firebase.ts +99 -99
- package/src/config/firebase.ts +78 -78
- package/src/config/index.ts +9 -9
- package/src/errors/auth.error.ts +6 -6
- package/src/errors/auth.errors.ts +200 -200
- package/src/errors/clinic.errors.ts +32 -32
- package/src/errors/firebase.errors.ts +47 -47
- package/src/errors/user.errors.ts +99 -99
- package/src/index.backup.ts +407 -407
- package/src/index.ts +6 -6
- package/src/locales/en.ts +31 -31
- package/src/recommender/admin/index.ts +1 -1
- package/src/recommender/admin/services/recommender.service.admin.ts +5 -5
- package/src/recommender/front/index.ts +1 -1
- package/src/recommender/front/services/onboarding.service.ts +5 -5
- package/src/recommender/front/services/recommender.service.ts +3 -3
- package/src/recommender/index.ts +1 -1
- package/src/services/PATIENTAUTH.MD +197 -197
- package/src/services/README.md +106 -106
- package/src/services/__tests__/auth/auth.mock.test.ts +17 -17
- package/src/services/__tests__/auth/auth.setup.ts +293 -293
- package/src/services/__tests__/auth.service.test.ts +346 -346
- package/src/services/__tests__/base.service.test.ts +77 -77
- package/src/services/__tests__/user.service.test.ts +528 -528
- package/src/services/analytics/ARCHITECTURE.md +199 -199
- package/src/services/analytics/CLOUD_FUNCTIONS.md +225 -225
- package/src/services/analytics/GROUPED_ANALYTICS.md +501 -501
- package/src/services/analytics/QUICK_START.md +393 -393
- package/src/services/analytics/README.md +304 -304
- package/src/services/analytics/SUMMARY.md +141 -141
- package/src/services/analytics/TRENDS.md +380 -380
- package/src/services/analytics/USAGE_GUIDE.md +518 -518
- package/src/services/analytics/analytics-cloud.service.ts +222 -222
- package/src/services/analytics/analytics.service.ts +2142 -2142
- package/src/services/analytics/index.ts +4 -4
- package/src/services/analytics/review-analytics.service.ts +941 -941
- package/src/services/analytics/utils/appointment-filtering.utils.ts +138 -138
- package/src/services/analytics/utils/cost-calculation.utils.ts +182 -182
- package/src/services/analytics/utils/grouping.utils.ts +434 -434
- package/src/services/analytics/utils/stored-analytics.utils.ts +347 -347
- package/src/services/analytics/utils/time-calculation.utils.ts +186 -186
- package/src/services/analytics/utils/trend-calculation.utils.ts +200 -200
- package/src/services/appointment/README.md +17 -17
- package/src/services/appointment/appointment.service.ts +2558 -2558
- package/src/services/appointment/index.ts +1 -1
- package/src/services/appointment/utils/appointment.utils.ts +552 -552
- package/src/services/appointment/utils/extended-procedure.utils.ts +314 -314
- package/src/services/appointment/utils/form-initialization.utils.ts +225 -225
- package/src/services/appointment/utils/recommended-procedure.utils.ts +195 -195
- package/src/services/appointment/utils/zone-management.utils.ts +353 -353
- package/src/services/appointment/utils/zone-photo.utils.ts +152 -152
- package/src/services/auth/auth.service.ts +989 -989
- package/src/services/auth/auth.v2.service.ts +961 -961
- package/src/services/auth/index.ts +7 -7
- package/src/services/auth/utils/error.utils.ts +90 -90
- package/src/services/auth/utils/firebase.utils.ts +49 -49
- package/src/services/auth/utils/index.ts +21 -21
- package/src/services/auth/utils/practitioner.utils.ts +125 -125
- package/src/services/base.service.ts +41 -41
- package/src/services/calendar/calendar.service.ts +1077 -1077
- package/src/services/calendar/calendar.v2.service.ts +1683 -1683
- package/src/services/calendar/calendar.v3.service.ts +313 -313
- package/src/services/calendar/externalCalendar.service.ts +178 -178
- package/src/services/calendar/index.ts +5 -5
- package/src/services/calendar/synced-calendars.service.ts +743 -743
- package/src/services/calendar/utils/appointment.utils.ts +265 -265
- package/src/services/calendar/utils/calendar-event.utils.ts +646 -646
- package/src/services/calendar/utils/clinic.utils.ts +237 -237
- package/src/services/calendar/utils/docs.utils.ts +157 -157
- package/src/services/calendar/utils/google-calendar.utils.ts +697 -697
- package/src/services/calendar/utils/index.ts +8 -8
- package/src/services/calendar/utils/patient.utils.ts +198 -198
- package/src/services/calendar/utils/practitioner.utils.ts +221 -221
- package/src/services/calendar/utils/synced-calendar.utils.ts +472 -472
- package/src/services/clinic/README.md +204 -204
- package/src/services/clinic/__tests__/clinic-admin.service.test.ts +287 -287
- package/src/services/clinic/__tests__/clinic-group.service.test.ts +352 -352
- package/src/services/clinic/__tests__/clinic.service.test.ts +354 -354
- package/src/services/clinic/billing-transactions.service.ts +217 -217
- package/src/services/clinic/clinic-admin.service.ts +202 -202
- package/src/services/clinic/clinic-group.service.ts +310 -310
- package/src/services/clinic/clinic.service.ts +708 -708
- package/src/services/clinic/index.ts +5 -5
- package/src/services/clinic/practitioner-invite.service.ts +519 -519
- package/src/services/clinic/utils/admin.utils.ts +551 -551
- package/src/services/clinic/utils/clinic-group.utils.ts +646 -646
- package/src/services/clinic/utils/clinic.utils.ts +949 -949
- package/src/services/clinic/utils/filter.utils.d.ts +23 -23
- package/src/services/clinic/utils/filter.utils.ts +446 -446
- package/src/services/clinic/utils/index.ts +11 -11
- package/src/services/clinic/utils/photos.utils.ts +188 -188
- package/src/services/clinic/utils/search.utils.ts +84 -84
- package/src/services/clinic/utils/tag.utils.ts +124 -124
- package/src/services/documentation-templates/documentation-template.service.ts +537 -537
- package/src/services/documentation-templates/filled-document.service.ts +587 -587
- package/src/services/documentation-templates/index.ts +2 -2
- package/src/services/index.ts +14 -14
- package/src/services/media/index.ts +1 -1
- package/src/services/media/media.service.ts +418 -418
- package/src/services/notifications/__tests__/notification.service.test.ts +242 -242
- package/src/services/notifications/index.ts +1 -1
- package/src/services/notifications/notification.service.ts +215 -215
- package/src/services/patient/README.md +48 -48
- package/src/services/patient/To-Do.md +43 -43
- package/src/services/patient/__tests__/patient.service.test.ts +294 -294
- package/src/services/patient/index.ts +2 -2
- package/src/services/patient/patient.service.ts +883 -883
- package/src/services/patient/patientRequirements.service.ts +285 -285
- package/src/services/patient/utils/aesthetic-analysis.utils.ts +176 -176
- package/src/services/patient/utils/clinic.utils.ts +80 -80
- package/src/services/patient/utils/docs.utils.ts +142 -142
- package/src/services/patient/utils/index.ts +9 -9
- package/src/services/patient/utils/location.utils.ts +126 -126
- package/src/services/patient/utils/medical-stuff.utils.ts +143 -143
- package/src/services/patient/utils/medical.utils.ts +458 -458
- package/src/services/patient/utils/practitioner.utils.ts +260 -260
- package/src/services/patient/utils/profile.utils.ts +510 -510
- package/src/services/patient/utils/sensitive.utils.ts +260 -260
- package/src/services/patient/utils/token.utils.ts +211 -211
- package/src/services/practitioner/README.md +145 -145
- package/src/services/practitioner/index.ts +1 -1
- package/src/services/practitioner/practitioner.service.ts +1742 -1742
- package/src/services/procedure/README.md +163 -163
- package/src/services/procedure/index.ts +1 -1
- package/src/services/procedure/procedure.service.ts +2200 -2200
- package/src/services/reviews/index.ts +1 -1
- package/src/services/reviews/reviews.service.ts +734 -734
- package/src/services/user/index.ts +1 -1
- package/src/services/user/user.service.ts +489 -489
- package/src/services/user/user.v2.service.ts +466 -466
- package/src/types/analytics/analytics.types.ts +597 -597
- package/src/types/analytics/grouped-analytics.types.ts +173 -173
- package/src/types/analytics/index.ts +4 -4
- package/src/types/analytics/stored-analytics.types.ts +137 -137
- package/src/types/appointment/index.ts +480 -480
- package/src/types/calendar/index.ts +258 -258
- package/src/types/calendar/synced-calendar.types.ts +66 -66
- package/src/types/clinic/index.ts +498 -489
- package/src/types/clinic/practitioner-invite.types.ts +91 -91
- package/src/types/clinic/preferences.types.ts +159 -159
- package/src/types/clinic/to-do +3 -3
- package/src/types/documentation-templates/index.ts +308 -308
- package/src/types/index.ts +47 -47
- package/src/types/notifications/README.md +77 -77
- package/src/types/notifications/index.ts +286 -286
- package/src/types/patient/aesthetic-analysis.types.ts +66 -66
- package/src/types/patient/allergies.ts +58 -58
- package/src/types/patient/index.ts +275 -275
- package/src/types/patient/medical-info.types.ts +152 -152
- package/src/types/patient/patient-requirements.ts +92 -92
- package/src/types/patient/token.types.ts +61 -61
- package/src/types/practitioner/index.ts +206 -206
- package/src/types/procedure/index.ts +181 -181
- package/src/types/profile/index.ts +39 -39
- package/src/types/reviews/index.ts +132 -132
- package/src/types/tz-lookup.d.ts +4 -4
- package/src/types/user/index.ts +38 -38
- package/src/utils/TIMESTAMPS.md +176 -176
- package/src/utils/TimestampUtils.ts +241 -241
- package/src/utils/index.ts +1 -1
- package/src/validations/appointment.schema.ts +574 -574
- package/src/validations/calendar.schema.ts +225 -225
- package/src/validations/clinic.schema.ts +494 -493
- package/src/validations/common.schema.ts +25 -25
- package/src/validations/documentation-templates/index.ts +1 -1
- package/src/validations/documentation-templates/template.schema.ts +220 -220
- package/src/validations/documentation-templates.schema.ts +10 -10
- package/src/validations/index.ts +20 -20
- package/src/validations/media.schema.ts +10 -10
- package/src/validations/notification.schema.ts +90 -90
- package/src/validations/patient/aesthetic-analysis.schema.ts +55 -55
- package/src/validations/patient/medical-info.schema.ts +125 -125
- package/src/validations/patient/patient-requirements.schema.ts +84 -84
- package/src/validations/patient/token.schema.ts +29 -29
- package/src/validations/patient.schema.ts +217 -217
- package/src/validations/practitioner.schema.ts +222 -222
- package/src/validations/procedure-product.schema.ts +41 -41
- package/src/validations/procedure.schema.ts +124 -124
- package/src/validations/profile-info.schema.ts +41 -41
- package/src/validations/reviews.schema.ts +195 -195
- package/src/validations/schemas.ts +104 -104
- package/src/validations/shared.schema.ts +78 -78
|
@@ -1,597 +1,597 @@
|
|
|
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
|
-
* Trend period type (only predefined periods, no custom)
|
|
37
|
-
*/
|
|
38
|
-
export type TrendPeriod = 'week' | 'month' | 'quarter' | 'year';
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Entity type for grouping analytics
|
|
42
|
-
*/
|
|
43
|
-
export type EntityType = 'clinic' | 'practitioner' | 'patient' | 'procedure' | 'technology';
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Practitioner Analytics
|
|
47
|
-
* Comprehensive metrics for a practitioner's performance
|
|
48
|
-
*/
|
|
49
|
-
export interface PractitionerAnalytics extends BaseMetrics {
|
|
50
|
-
practitionerId: string;
|
|
51
|
-
practitionerName: string;
|
|
52
|
-
totalAppointments: number;
|
|
53
|
-
completedAppointments: number;
|
|
54
|
-
canceledAppointments: number;
|
|
55
|
-
noShowAppointments: number;
|
|
56
|
-
pendingAppointments: number;
|
|
57
|
-
confirmedAppointments: number;
|
|
58
|
-
cancellationRate: number; // percentage
|
|
59
|
-
noShowRate: number; // percentage
|
|
60
|
-
averageBookedTime: number; // minutes
|
|
61
|
-
averageActualTime: number; // minutes
|
|
62
|
-
timeEfficiency: number; // percentage
|
|
63
|
-
totalRevenue: number;
|
|
64
|
-
averageRevenuePerAppointment: number;
|
|
65
|
-
currency: string;
|
|
66
|
-
topProcedures: Array<{
|
|
67
|
-
procedureId: string;
|
|
68
|
-
procedureName: string;
|
|
69
|
-
count: number;
|
|
70
|
-
revenue: number;
|
|
71
|
-
}>;
|
|
72
|
-
patientRetentionRate: number; // percentage
|
|
73
|
-
uniquePatients: number;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Procedure Analytics
|
|
78
|
-
* Comprehensive metrics for procedure performance
|
|
79
|
-
*/
|
|
80
|
-
export interface ProcedureAnalytics extends BaseMetrics {
|
|
81
|
-
procedureId: string;
|
|
82
|
-
procedureName: string;
|
|
83
|
-
procedureFamily: string;
|
|
84
|
-
categoryName: string;
|
|
85
|
-
subcategoryName: string;
|
|
86
|
-
technologyName: string;
|
|
87
|
-
totalAppointments: number;
|
|
88
|
-
completedAppointments: number;
|
|
89
|
-
canceledAppointments: number;
|
|
90
|
-
noShowAppointments: number;
|
|
91
|
-
cancellationRate: number; // percentage
|
|
92
|
-
noShowRate: number; // percentage
|
|
93
|
-
averageCost: number;
|
|
94
|
-
totalRevenue: number;
|
|
95
|
-
averageRevenuePerAppointment: number;
|
|
96
|
-
currency: string;
|
|
97
|
-
averageBookedDuration: number; // minutes
|
|
98
|
-
averageActualDuration: number; // minutes
|
|
99
|
-
productUsage: Array<{
|
|
100
|
-
productId: string;
|
|
101
|
-
productName: string;
|
|
102
|
-
brandName: string;
|
|
103
|
-
totalQuantity: number;
|
|
104
|
-
totalRevenue: number;
|
|
105
|
-
usageCount: number;
|
|
106
|
-
}>;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Time Efficiency Metrics
|
|
111
|
-
* Analysis of booked time vs actual time spent
|
|
112
|
-
*/
|
|
113
|
-
export interface TimeEfficiencyMetrics {
|
|
114
|
-
totalAppointments: number;
|
|
115
|
-
appointmentsWithActualTime: number;
|
|
116
|
-
averageBookedDuration: number; // minutes
|
|
117
|
-
averageActualDuration: number; // minutes
|
|
118
|
-
averageEfficiency: number; // percentage
|
|
119
|
-
totalOverrun: number; // minutes
|
|
120
|
-
totalUnderutilization: number; // minutes
|
|
121
|
-
averageOverrun: number; // minutes
|
|
122
|
-
averageUnderutilization: number; // minutes
|
|
123
|
-
efficiencyDistribution: Array<{
|
|
124
|
-
range: string; // e.g., "0-50%", "50-75%", "75-100%", "100%+"
|
|
125
|
-
count: number;
|
|
126
|
-
percentage: number;
|
|
127
|
-
}>;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Cancellation Metrics
|
|
132
|
-
* Analysis of appointment cancellations
|
|
133
|
-
*/
|
|
134
|
-
export interface CancellationMetrics {
|
|
135
|
-
entityId: string;
|
|
136
|
-
entityName: string;
|
|
137
|
-
entityType: EntityType;
|
|
138
|
-
totalAppointments: number;
|
|
139
|
-
canceledAppointments: number;
|
|
140
|
-
cancellationRate: number; // percentage
|
|
141
|
-
canceledByPatient: number;
|
|
142
|
-
canceledByClinic: number;
|
|
143
|
-
canceledByPractitioner: number;
|
|
144
|
-
canceledRescheduled: number;
|
|
145
|
-
averageCancellationLeadTime: number; // hours
|
|
146
|
-
cancellationReasons: Array<{
|
|
147
|
-
reason: string;
|
|
148
|
-
count: number;
|
|
149
|
-
percentage: number;
|
|
150
|
-
}>;
|
|
151
|
-
// Practitioner info when grouping by procedure
|
|
152
|
-
practitionerId?: string;
|
|
153
|
-
practitionerName?: string;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* No-Show Metrics
|
|
158
|
-
* Analysis of appointment no-shows
|
|
159
|
-
*/
|
|
160
|
-
export interface NoShowMetrics {
|
|
161
|
-
entityId: string;
|
|
162
|
-
entityName: string;
|
|
163
|
-
entityType: EntityType;
|
|
164
|
-
totalAppointments: number;
|
|
165
|
-
noShowAppointments: number;
|
|
166
|
-
noShowRate: number; // percentage
|
|
167
|
-
// Practitioner info when grouping by procedure
|
|
168
|
-
practitionerId?: string;
|
|
169
|
-
practitionerName?: string;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Revenue Metrics
|
|
174
|
-
* Financial analysis and revenue tracking
|
|
175
|
-
*/
|
|
176
|
-
export interface RevenueMetrics {
|
|
177
|
-
totalRevenue: number;
|
|
178
|
-
averageRevenuePerAppointment: number;
|
|
179
|
-
totalAppointments: number;
|
|
180
|
-
completedAppointments: number;
|
|
181
|
-
currency: string;
|
|
182
|
-
revenueByStatus: Partial<Record<AppointmentStatus, number>>;
|
|
183
|
-
revenueByPaymentStatus: Partial<Record<PaymentStatus, number>>;
|
|
184
|
-
unpaidRevenue: number;
|
|
185
|
-
refundedRevenue: number;
|
|
186
|
-
totalTax: number;
|
|
187
|
-
totalSubtotal: number;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Revenue Trend
|
|
192
|
-
* Revenue data over time
|
|
193
|
-
*/
|
|
194
|
-
export interface RevenueTrend {
|
|
195
|
-
period: string; // e.g., "2024-W01", "2024-01", "2024-Q1", "2024"
|
|
196
|
-
startDate: Date;
|
|
197
|
-
endDate: Date;
|
|
198
|
-
revenue: number;
|
|
199
|
-
appointmentCount: number;
|
|
200
|
-
averageRevenue: number;
|
|
201
|
-
currency?: string;
|
|
202
|
-
// Trend comparison (compared to previous period)
|
|
203
|
-
previousPeriod?: {
|
|
204
|
-
revenue: number;
|
|
205
|
-
appointmentCount: number;
|
|
206
|
-
percentageChange: number;
|
|
207
|
-
direction: 'up' | 'down' | 'stable';
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* Duration Trend
|
|
213
|
-
* Appointment duration trends over time
|
|
214
|
-
*/
|
|
215
|
-
export interface DurationTrend {
|
|
216
|
-
period: string;
|
|
217
|
-
startDate: Date;
|
|
218
|
-
endDate: Date;
|
|
219
|
-
averageBookedDuration: number; // minutes
|
|
220
|
-
averageActualDuration: number; // minutes
|
|
221
|
-
averageEfficiency: number; // percentage
|
|
222
|
-
appointmentCount: number;
|
|
223
|
-
// Trend comparison (compared to previous period)
|
|
224
|
-
previousPeriod?: {
|
|
225
|
-
averageBookedDuration: number;
|
|
226
|
-
averageActualDuration: number;
|
|
227
|
-
averageEfficiency: number;
|
|
228
|
-
efficiencyPercentageChange: number;
|
|
229
|
-
direction: 'up' | 'down' | 'stable';
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* Appointment Count Trend
|
|
235
|
-
* Appointment count trends over time
|
|
236
|
-
*/
|
|
237
|
-
export interface AppointmentTrend {
|
|
238
|
-
period: string;
|
|
239
|
-
startDate: Date;
|
|
240
|
-
endDate: Date;
|
|
241
|
-
totalAppointments: number;
|
|
242
|
-
completedAppointments: number;
|
|
243
|
-
canceledAppointments: number;
|
|
244
|
-
noShowAppointments: number;
|
|
245
|
-
pendingAppointments: number;
|
|
246
|
-
confirmedAppointments: number;
|
|
247
|
-
// Trend comparison (compared to previous period)
|
|
248
|
-
previousPeriod?: {
|
|
249
|
-
totalAppointments: number;
|
|
250
|
-
completedAppointments: number;
|
|
251
|
-
percentageChange: number;
|
|
252
|
-
direction: 'up' | 'down' | 'stable';
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* Cancellation Rate Trend
|
|
258
|
-
* Cancellation and no-show rate trends over time
|
|
259
|
-
*/
|
|
260
|
-
export interface CancellationRateTrend {
|
|
261
|
-
period: string;
|
|
262
|
-
startDate: Date;
|
|
263
|
-
endDate: Date;
|
|
264
|
-
cancellationRate: number; // percentage
|
|
265
|
-
noShowRate: number; // percentage
|
|
266
|
-
totalAppointments: number;
|
|
267
|
-
canceledAppointments: number;
|
|
268
|
-
noShowAppointments: number;
|
|
269
|
-
// Trend comparison (compared to previous period)
|
|
270
|
-
previousPeriod?: {
|
|
271
|
-
cancellationRate: number;
|
|
272
|
-
noShowRate: number;
|
|
273
|
-
cancellationRateChange: number;
|
|
274
|
-
noShowRateChange: number;
|
|
275
|
-
direction: 'up' | 'down' | 'stable';
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
* Review Trend
|
|
281
|
-
* Review rating and recommendation trends over time
|
|
282
|
-
*/
|
|
283
|
-
export interface ReviewTrend {
|
|
284
|
-
period: string; // e.g., "2024-W01", "2024-01", "2024-Q1", "2024"
|
|
285
|
-
startDate: Date;
|
|
286
|
-
endDate: Date;
|
|
287
|
-
averageRating: number; // weighted average rating (0-5)
|
|
288
|
-
recommendationRate: number; // percentage
|
|
289
|
-
totalReviews: number;
|
|
290
|
-
practitionerAverage?: number; // if tracking practitioner reviews
|
|
291
|
-
procedureAverage?: number; // if tracking procedure reviews
|
|
292
|
-
// Trend comparison (compared to previous period)
|
|
293
|
-
previousPeriod?: {
|
|
294
|
-
averageRating: number;
|
|
295
|
-
recommendationRate: number;
|
|
296
|
-
percentageChange: number; // for average rating
|
|
297
|
-
direction: 'up' | 'down' | 'stable';
|
|
298
|
-
};
|
|
299
|
-
entityId?: string; // if grouped by entity
|
|
300
|
-
entityName?: string;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
/**
|
|
304
|
-
* Product Usage Metrics
|
|
305
|
-
* Analysis of product usage in appointments
|
|
306
|
-
*/
|
|
307
|
-
export interface ProductUsageMetrics {
|
|
308
|
-
productId: string;
|
|
309
|
-
productName: string;
|
|
310
|
-
brandId: string;
|
|
311
|
-
brandName: string;
|
|
312
|
-
totalQuantity: number;
|
|
313
|
-
totalRevenue: number;
|
|
314
|
-
averagePrice: number;
|
|
315
|
-
currency: string;
|
|
316
|
-
usageCount: number; // number of appointments using this product
|
|
317
|
-
averageQuantityPerAppointment: number;
|
|
318
|
-
usageByProcedure: Array<{
|
|
319
|
-
procedureId: string;
|
|
320
|
-
procedureName: string;
|
|
321
|
-
count: number;
|
|
322
|
-
totalQuantity: number;
|
|
323
|
-
}>;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
/**
|
|
327
|
-
* Product Revenue Metrics
|
|
328
|
-
* Revenue contribution by product
|
|
329
|
-
*/
|
|
330
|
-
export interface ProductRevenueMetrics {
|
|
331
|
-
productId: string;
|
|
332
|
-
productName: string;
|
|
333
|
-
brandName: string;
|
|
334
|
-
totalRevenue: number;
|
|
335
|
-
currency: string;
|
|
336
|
-
usageCount: number;
|
|
337
|
-
averageRevenuePerUsage: number;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
/**
|
|
341
|
-
* Product Usage by Procedure
|
|
342
|
-
* Product usage patterns for specific procedures
|
|
343
|
-
*/
|
|
344
|
-
export interface ProductUsageByProcedure {
|
|
345
|
-
procedureId: string;
|
|
346
|
-
procedureName: string;
|
|
347
|
-
products: Array<{
|
|
348
|
-
productId: string;
|
|
349
|
-
productName: string;
|
|
350
|
-
brandName: string;
|
|
351
|
-
totalQuantity: number;
|
|
352
|
-
totalRevenue: number;
|
|
353
|
-
usageCount: number;
|
|
354
|
-
}>;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
/**
|
|
358
|
-
* Patient Analytics
|
|
359
|
-
* Comprehensive patient metrics
|
|
360
|
-
*/
|
|
361
|
-
export interface PatientAnalytics {
|
|
362
|
-
patientId: string;
|
|
363
|
-
patientName: string;
|
|
364
|
-
totalAppointments: number;
|
|
365
|
-
completedAppointments: number;
|
|
366
|
-
canceledAppointments: number;
|
|
367
|
-
noShowAppointments: number;
|
|
368
|
-
cancellationRate: number; // percentage
|
|
369
|
-
noShowRate: number; // percentage
|
|
370
|
-
totalRevenue: number;
|
|
371
|
-
averageRevenuePerAppointment: number;
|
|
372
|
-
currency: string;
|
|
373
|
-
lifetimeValue: number;
|
|
374
|
-
firstAppointmentDate: Date | null;
|
|
375
|
-
lastAppointmentDate: Date | null;
|
|
376
|
-
averageDaysBetweenAppointments: number | null;
|
|
377
|
-
uniquePractitioners: number;
|
|
378
|
-
uniqueClinics: number;
|
|
379
|
-
favoriteProcedures: Array<{
|
|
380
|
-
procedureId: string;
|
|
381
|
-
procedureName: string;
|
|
382
|
-
count: number;
|
|
383
|
-
}>;
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
/**
|
|
387
|
-
* Patient Lifetime Value Metrics
|
|
388
|
-
* Patient value analysis
|
|
389
|
-
*/
|
|
390
|
-
export interface PatientLifetimeValueMetrics {
|
|
391
|
-
totalPatients: number;
|
|
392
|
-
averageLifetimeValue: number;
|
|
393
|
-
currency: string;
|
|
394
|
-
topPatients: Array<{
|
|
395
|
-
patientId: string;
|
|
396
|
-
patientName: string;
|
|
397
|
-
lifetimeValue: number;
|
|
398
|
-
appointmentCount: number;
|
|
399
|
-
}>;
|
|
400
|
-
valueDistribution: Array<{
|
|
401
|
-
range: string; // e.g., "0-500", "500-1000", "1000+"
|
|
402
|
-
count: number;
|
|
403
|
-
percentage: number;
|
|
404
|
-
}>;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
/**
|
|
408
|
-
* Patient Retention Metrics
|
|
409
|
-
* Patient retention and return analysis
|
|
410
|
-
*/
|
|
411
|
-
export interface PatientRetentionMetrics {
|
|
412
|
-
totalPatients: number;
|
|
413
|
-
newPatients: number;
|
|
414
|
-
returningPatients: number;
|
|
415
|
-
retentionRate: number; // percentage
|
|
416
|
-
averageAppointmentsPerPatient: number;
|
|
417
|
-
patientsByAppointmentCount: Array<{
|
|
418
|
-
appointmentCount: number;
|
|
419
|
-
patientCount: number;
|
|
420
|
-
percentage: number;
|
|
421
|
-
}>;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
/**
|
|
425
|
-
* Cost Per Patient Metrics
|
|
426
|
-
* Cost analysis per patient
|
|
427
|
-
*/
|
|
428
|
-
export interface CostPerPatientMetrics {
|
|
429
|
-
totalPatients: number;
|
|
430
|
-
totalRevenue: number;
|
|
431
|
-
averageCostPerPatient: number;
|
|
432
|
-
currency: string;
|
|
433
|
-
costDistribution: Array<{
|
|
434
|
-
range: string;
|
|
435
|
-
patientCount: number;
|
|
436
|
-
percentage: number;
|
|
437
|
-
}>;
|
|
438
|
-
patientCosts?: Array<{
|
|
439
|
-
patientId: string;
|
|
440
|
-
patientName: string;
|
|
441
|
-
totalCost: number;
|
|
442
|
-
appointmentCount: number;
|
|
443
|
-
averageCost: number;
|
|
444
|
-
}>;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
/**
|
|
448
|
-
* Payment Status Breakdown
|
|
449
|
-
* Analysis of payment statuses
|
|
450
|
-
*/
|
|
451
|
-
export interface PaymentStatusBreakdown {
|
|
452
|
-
totalAppointments: number;
|
|
453
|
-
byStatus: Partial<Record<PaymentStatus, {
|
|
454
|
-
count: number;
|
|
455
|
-
percentage: number;
|
|
456
|
-
totalRevenue: number;
|
|
457
|
-
}>>;
|
|
458
|
-
unpaidCount: number;
|
|
459
|
-
unpaidRevenue: number;
|
|
460
|
-
paidCount: number;
|
|
461
|
-
paidRevenue: number;
|
|
462
|
-
partiallyPaidCount: number;
|
|
463
|
-
partiallyPaidRevenue: number;
|
|
464
|
-
refundedCount: number;
|
|
465
|
-
refundedRevenue: number;
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
/**
|
|
469
|
-
* Clinic Analytics
|
|
470
|
-
* Comprehensive clinic performance metrics
|
|
471
|
-
*/
|
|
472
|
-
export interface ClinicAnalytics {
|
|
473
|
-
clinicBranchId: string;
|
|
474
|
-
clinicName: string;
|
|
475
|
-
totalAppointments: number;
|
|
476
|
-
completedAppointments: number;
|
|
477
|
-
canceledAppointments: number;
|
|
478
|
-
noShowAppointments: number;
|
|
479
|
-
cancellationRate: number; // percentage
|
|
480
|
-
noShowRate: number; // percentage
|
|
481
|
-
totalRevenue: number;
|
|
482
|
-
averageRevenuePerAppointment: number;
|
|
483
|
-
currency: string;
|
|
484
|
-
practitionerCount: number;
|
|
485
|
-
patientCount: number;
|
|
486
|
-
procedureCount: number;
|
|
487
|
-
topPractitioners: Array<{
|
|
488
|
-
practitionerId: string;
|
|
489
|
-
practitionerName: string;
|
|
490
|
-
appointmentCount: number;
|
|
491
|
-
revenue: number;
|
|
492
|
-
}>;
|
|
493
|
-
topProcedures: Array<{
|
|
494
|
-
procedureId: string;
|
|
495
|
-
procedureName: string;
|
|
496
|
-
appointmentCount: number;
|
|
497
|
-
revenue: number;
|
|
498
|
-
}>;
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
/**
|
|
502
|
-
* Clinic Comparison Metrics
|
|
503
|
-
* Comparison data for multiple clinics
|
|
504
|
-
*/
|
|
505
|
-
export interface ClinicComparisonMetrics {
|
|
506
|
-
clinicBranchId: string;
|
|
507
|
-
clinicName: string;
|
|
508
|
-
totalAppointments: number;
|
|
509
|
-
completedAppointments: number;
|
|
510
|
-
cancellationRate: number;
|
|
511
|
-
noShowRate: number;
|
|
512
|
-
totalRevenue: number;
|
|
513
|
-
averageRevenuePerAppointment: number;
|
|
514
|
-
practitionerCount: number;
|
|
515
|
-
patientCount: number;
|
|
516
|
-
efficiency: number; // percentage
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
/**
|
|
520
|
-
* Procedure Popularity
|
|
521
|
-
* Popularity metrics for procedures
|
|
522
|
-
*/
|
|
523
|
-
export interface ProcedurePopularity {
|
|
524
|
-
procedureId: string;
|
|
525
|
-
procedureName: string;
|
|
526
|
-
categoryName: string;
|
|
527
|
-
subcategoryName: string;
|
|
528
|
-
technologyName: string;
|
|
529
|
-
appointmentCount: number;
|
|
530
|
-
completedCount: number;
|
|
531
|
-
rank: number;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
/**
|
|
535
|
-
* Procedure Profitability
|
|
536
|
-
* Profitability metrics for procedures
|
|
537
|
-
*/
|
|
538
|
-
export interface ProcedureProfitability {
|
|
539
|
-
procedureId: string;
|
|
540
|
-
procedureName: string;
|
|
541
|
-
categoryName: string;
|
|
542
|
-
subcategoryName: string;
|
|
543
|
-
technologyName: string;
|
|
544
|
-
totalRevenue: number;
|
|
545
|
-
averageRevenue: number;
|
|
546
|
-
appointmentCount: number;
|
|
547
|
-
rank: number;
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
/**
|
|
551
|
-
* Cancellation Reason Statistics
|
|
552
|
-
* Breakdown of cancellation reasons
|
|
553
|
-
*/
|
|
554
|
-
export interface CancellationReasonStats {
|
|
555
|
-
reason: string;
|
|
556
|
-
count: number;
|
|
557
|
-
percentage: number;
|
|
558
|
-
averageLeadTime: number; // hours
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
/**
|
|
562
|
-
* Dashboard Analytics
|
|
563
|
-
* Comprehensive dashboard data aggregation
|
|
564
|
-
*/
|
|
565
|
-
export interface DashboardAnalytics {
|
|
566
|
-
overview: {
|
|
567
|
-
totalAppointments: number;
|
|
568
|
-
completedAppointments: number;
|
|
569
|
-
canceledAppointments: number;
|
|
570
|
-
noShowAppointments: number;
|
|
571
|
-
pendingAppointments: number;
|
|
572
|
-
confirmedAppointments: number;
|
|
573
|
-
totalRevenue: number;
|
|
574
|
-
averageRevenuePerAppointment: number;
|
|
575
|
-
currency: string;
|
|
576
|
-
uniquePatients: number;
|
|
577
|
-
uniquePractitioners: number;
|
|
578
|
-
uniqueProcedures: number;
|
|
579
|
-
cancellationRate: number;
|
|
580
|
-
noShowRate: number;
|
|
581
|
-
};
|
|
582
|
-
practitionerMetrics: PractitionerAnalytics[];
|
|
583
|
-
procedureMetrics: ProcedureAnalytics[];
|
|
584
|
-
cancellationMetrics: CancellationMetrics;
|
|
585
|
-
noShowMetrics: NoShowMetrics;
|
|
586
|
-
revenueTrends: RevenueTrend[];
|
|
587
|
-
timeEfficiency: TimeEfficiencyMetrics;
|
|
588
|
-
topProducts: ProductUsageMetrics[];
|
|
589
|
-
recentActivity: Array<{
|
|
590
|
-
type: 'appointment' | 'cancellation' | 'completion' | 'no_show';
|
|
591
|
-
date: Date;
|
|
592
|
-
description: string;
|
|
593
|
-
entityId?: string;
|
|
594
|
-
entityName?: string;
|
|
595
|
-
}>;
|
|
596
|
-
}
|
|
597
|
-
|
|
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
|
+
* Trend period type (only predefined periods, no custom)
|
|
37
|
+
*/
|
|
38
|
+
export type TrendPeriod = 'week' | 'month' | 'quarter' | 'year';
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Entity type for grouping analytics
|
|
42
|
+
*/
|
|
43
|
+
export type EntityType = 'clinic' | 'practitioner' | 'patient' | 'procedure' | 'technology';
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Practitioner Analytics
|
|
47
|
+
* Comprehensive metrics for a practitioner's performance
|
|
48
|
+
*/
|
|
49
|
+
export interface PractitionerAnalytics extends BaseMetrics {
|
|
50
|
+
practitionerId: string;
|
|
51
|
+
practitionerName: string;
|
|
52
|
+
totalAppointments: number;
|
|
53
|
+
completedAppointments: number;
|
|
54
|
+
canceledAppointments: number;
|
|
55
|
+
noShowAppointments: number;
|
|
56
|
+
pendingAppointments: number;
|
|
57
|
+
confirmedAppointments: number;
|
|
58
|
+
cancellationRate: number; // percentage
|
|
59
|
+
noShowRate: number; // percentage
|
|
60
|
+
averageBookedTime: number; // minutes
|
|
61
|
+
averageActualTime: number; // minutes
|
|
62
|
+
timeEfficiency: number; // percentage
|
|
63
|
+
totalRevenue: number;
|
|
64
|
+
averageRevenuePerAppointment: number;
|
|
65
|
+
currency: string;
|
|
66
|
+
topProcedures: Array<{
|
|
67
|
+
procedureId: string;
|
|
68
|
+
procedureName: string;
|
|
69
|
+
count: number;
|
|
70
|
+
revenue: number;
|
|
71
|
+
}>;
|
|
72
|
+
patientRetentionRate: number; // percentage
|
|
73
|
+
uniquePatients: number;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Procedure Analytics
|
|
78
|
+
* Comprehensive metrics for procedure performance
|
|
79
|
+
*/
|
|
80
|
+
export interface ProcedureAnalytics extends BaseMetrics {
|
|
81
|
+
procedureId: string;
|
|
82
|
+
procedureName: string;
|
|
83
|
+
procedureFamily: string;
|
|
84
|
+
categoryName: string;
|
|
85
|
+
subcategoryName: string;
|
|
86
|
+
technologyName: string;
|
|
87
|
+
totalAppointments: number;
|
|
88
|
+
completedAppointments: number;
|
|
89
|
+
canceledAppointments: number;
|
|
90
|
+
noShowAppointments: number;
|
|
91
|
+
cancellationRate: number; // percentage
|
|
92
|
+
noShowRate: number; // percentage
|
|
93
|
+
averageCost: number;
|
|
94
|
+
totalRevenue: number;
|
|
95
|
+
averageRevenuePerAppointment: number;
|
|
96
|
+
currency: string;
|
|
97
|
+
averageBookedDuration: number; // minutes
|
|
98
|
+
averageActualDuration: number; // minutes
|
|
99
|
+
productUsage: Array<{
|
|
100
|
+
productId: string;
|
|
101
|
+
productName: string;
|
|
102
|
+
brandName: string;
|
|
103
|
+
totalQuantity: number;
|
|
104
|
+
totalRevenue: number;
|
|
105
|
+
usageCount: number;
|
|
106
|
+
}>;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Time Efficiency Metrics
|
|
111
|
+
* Analysis of booked time vs actual time spent
|
|
112
|
+
*/
|
|
113
|
+
export interface TimeEfficiencyMetrics {
|
|
114
|
+
totalAppointments: number;
|
|
115
|
+
appointmentsWithActualTime: number;
|
|
116
|
+
averageBookedDuration: number; // minutes
|
|
117
|
+
averageActualDuration: number; // minutes
|
|
118
|
+
averageEfficiency: number; // percentage
|
|
119
|
+
totalOverrun: number; // minutes
|
|
120
|
+
totalUnderutilization: number; // minutes
|
|
121
|
+
averageOverrun: number; // minutes
|
|
122
|
+
averageUnderutilization: number; // minutes
|
|
123
|
+
efficiencyDistribution: Array<{
|
|
124
|
+
range: string; // e.g., "0-50%", "50-75%", "75-100%", "100%+"
|
|
125
|
+
count: number;
|
|
126
|
+
percentage: number;
|
|
127
|
+
}>;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Cancellation Metrics
|
|
132
|
+
* Analysis of appointment cancellations
|
|
133
|
+
*/
|
|
134
|
+
export interface CancellationMetrics {
|
|
135
|
+
entityId: string;
|
|
136
|
+
entityName: string;
|
|
137
|
+
entityType: EntityType;
|
|
138
|
+
totalAppointments: number;
|
|
139
|
+
canceledAppointments: number;
|
|
140
|
+
cancellationRate: number; // percentage
|
|
141
|
+
canceledByPatient: number;
|
|
142
|
+
canceledByClinic: number;
|
|
143
|
+
canceledByPractitioner: number;
|
|
144
|
+
canceledRescheduled: number;
|
|
145
|
+
averageCancellationLeadTime: number; // hours
|
|
146
|
+
cancellationReasons: Array<{
|
|
147
|
+
reason: string;
|
|
148
|
+
count: number;
|
|
149
|
+
percentage: number;
|
|
150
|
+
}>;
|
|
151
|
+
// Practitioner info when grouping by procedure
|
|
152
|
+
practitionerId?: string;
|
|
153
|
+
practitionerName?: string;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* No-Show Metrics
|
|
158
|
+
* Analysis of appointment no-shows
|
|
159
|
+
*/
|
|
160
|
+
export interface NoShowMetrics {
|
|
161
|
+
entityId: string;
|
|
162
|
+
entityName: string;
|
|
163
|
+
entityType: EntityType;
|
|
164
|
+
totalAppointments: number;
|
|
165
|
+
noShowAppointments: number;
|
|
166
|
+
noShowRate: number; // percentage
|
|
167
|
+
// Practitioner info when grouping by procedure
|
|
168
|
+
practitionerId?: string;
|
|
169
|
+
practitionerName?: string;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Revenue Metrics
|
|
174
|
+
* Financial analysis and revenue tracking
|
|
175
|
+
*/
|
|
176
|
+
export interface RevenueMetrics {
|
|
177
|
+
totalRevenue: number;
|
|
178
|
+
averageRevenuePerAppointment: number;
|
|
179
|
+
totalAppointments: number;
|
|
180
|
+
completedAppointments: number;
|
|
181
|
+
currency: string;
|
|
182
|
+
revenueByStatus: Partial<Record<AppointmentStatus, number>>;
|
|
183
|
+
revenueByPaymentStatus: Partial<Record<PaymentStatus, number>>;
|
|
184
|
+
unpaidRevenue: number;
|
|
185
|
+
refundedRevenue: number;
|
|
186
|
+
totalTax: number;
|
|
187
|
+
totalSubtotal: number;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Revenue Trend
|
|
192
|
+
* Revenue data over time
|
|
193
|
+
*/
|
|
194
|
+
export interface RevenueTrend {
|
|
195
|
+
period: string; // e.g., "2024-W01", "2024-01", "2024-Q1", "2024"
|
|
196
|
+
startDate: Date;
|
|
197
|
+
endDate: Date;
|
|
198
|
+
revenue: number;
|
|
199
|
+
appointmentCount: number;
|
|
200
|
+
averageRevenue: number;
|
|
201
|
+
currency?: string;
|
|
202
|
+
// Trend comparison (compared to previous period)
|
|
203
|
+
previousPeriod?: {
|
|
204
|
+
revenue: number;
|
|
205
|
+
appointmentCount: number;
|
|
206
|
+
percentageChange: number;
|
|
207
|
+
direction: 'up' | 'down' | 'stable';
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Duration Trend
|
|
213
|
+
* Appointment duration trends over time
|
|
214
|
+
*/
|
|
215
|
+
export interface DurationTrend {
|
|
216
|
+
period: string;
|
|
217
|
+
startDate: Date;
|
|
218
|
+
endDate: Date;
|
|
219
|
+
averageBookedDuration: number; // minutes
|
|
220
|
+
averageActualDuration: number; // minutes
|
|
221
|
+
averageEfficiency: number; // percentage
|
|
222
|
+
appointmentCount: number;
|
|
223
|
+
// Trend comparison (compared to previous period)
|
|
224
|
+
previousPeriod?: {
|
|
225
|
+
averageBookedDuration: number;
|
|
226
|
+
averageActualDuration: number;
|
|
227
|
+
averageEfficiency: number;
|
|
228
|
+
efficiencyPercentageChange: number;
|
|
229
|
+
direction: 'up' | 'down' | 'stable';
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Appointment Count Trend
|
|
235
|
+
* Appointment count trends over time
|
|
236
|
+
*/
|
|
237
|
+
export interface AppointmentTrend {
|
|
238
|
+
period: string;
|
|
239
|
+
startDate: Date;
|
|
240
|
+
endDate: Date;
|
|
241
|
+
totalAppointments: number;
|
|
242
|
+
completedAppointments: number;
|
|
243
|
+
canceledAppointments: number;
|
|
244
|
+
noShowAppointments: number;
|
|
245
|
+
pendingAppointments: number;
|
|
246
|
+
confirmedAppointments: number;
|
|
247
|
+
// Trend comparison (compared to previous period)
|
|
248
|
+
previousPeriod?: {
|
|
249
|
+
totalAppointments: number;
|
|
250
|
+
completedAppointments: number;
|
|
251
|
+
percentageChange: number;
|
|
252
|
+
direction: 'up' | 'down' | 'stable';
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Cancellation Rate Trend
|
|
258
|
+
* Cancellation and no-show rate trends over time
|
|
259
|
+
*/
|
|
260
|
+
export interface CancellationRateTrend {
|
|
261
|
+
period: string;
|
|
262
|
+
startDate: Date;
|
|
263
|
+
endDate: Date;
|
|
264
|
+
cancellationRate: number; // percentage
|
|
265
|
+
noShowRate: number; // percentage
|
|
266
|
+
totalAppointments: number;
|
|
267
|
+
canceledAppointments: number;
|
|
268
|
+
noShowAppointments: number;
|
|
269
|
+
// Trend comparison (compared to previous period)
|
|
270
|
+
previousPeriod?: {
|
|
271
|
+
cancellationRate: number;
|
|
272
|
+
noShowRate: number;
|
|
273
|
+
cancellationRateChange: number;
|
|
274
|
+
noShowRateChange: number;
|
|
275
|
+
direction: 'up' | 'down' | 'stable';
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Review Trend
|
|
281
|
+
* Review rating and recommendation trends over time
|
|
282
|
+
*/
|
|
283
|
+
export interface ReviewTrend {
|
|
284
|
+
period: string; // e.g., "2024-W01", "2024-01", "2024-Q1", "2024"
|
|
285
|
+
startDate: Date;
|
|
286
|
+
endDate: Date;
|
|
287
|
+
averageRating: number; // weighted average rating (0-5)
|
|
288
|
+
recommendationRate: number; // percentage
|
|
289
|
+
totalReviews: number;
|
|
290
|
+
practitionerAverage?: number; // if tracking practitioner reviews
|
|
291
|
+
procedureAverage?: number; // if tracking procedure reviews
|
|
292
|
+
// Trend comparison (compared to previous period)
|
|
293
|
+
previousPeriod?: {
|
|
294
|
+
averageRating: number;
|
|
295
|
+
recommendationRate: number;
|
|
296
|
+
percentageChange: number; // for average rating
|
|
297
|
+
direction: 'up' | 'down' | 'stable';
|
|
298
|
+
};
|
|
299
|
+
entityId?: string; // if grouped by entity
|
|
300
|
+
entityName?: string;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Product Usage Metrics
|
|
305
|
+
* Analysis of product usage in appointments
|
|
306
|
+
*/
|
|
307
|
+
export interface ProductUsageMetrics {
|
|
308
|
+
productId: string;
|
|
309
|
+
productName: string;
|
|
310
|
+
brandId: string;
|
|
311
|
+
brandName: string;
|
|
312
|
+
totalQuantity: number;
|
|
313
|
+
totalRevenue: number;
|
|
314
|
+
averagePrice: number;
|
|
315
|
+
currency: string;
|
|
316
|
+
usageCount: number; // number of appointments using this product
|
|
317
|
+
averageQuantityPerAppointment: number;
|
|
318
|
+
usageByProcedure: Array<{
|
|
319
|
+
procedureId: string;
|
|
320
|
+
procedureName: string;
|
|
321
|
+
count: number;
|
|
322
|
+
totalQuantity: number;
|
|
323
|
+
}>;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Product Revenue Metrics
|
|
328
|
+
* Revenue contribution by product
|
|
329
|
+
*/
|
|
330
|
+
export interface ProductRevenueMetrics {
|
|
331
|
+
productId: string;
|
|
332
|
+
productName: string;
|
|
333
|
+
brandName: string;
|
|
334
|
+
totalRevenue: number;
|
|
335
|
+
currency: string;
|
|
336
|
+
usageCount: number;
|
|
337
|
+
averageRevenuePerUsage: number;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Product Usage by Procedure
|
|
342
|
+
* Product usage patterns for specific procedures
|
|
343
|
+
*/
|
|
344
|
+
export interface ProductUsageByProcedure {
|
|
345
|
+
procedureId: string;
|
|
346
|
+
procedureName: string;
|
|
347
|
+
products: Array<{
|
|
348
|
+
productId: string;
|
|
349
|
+
productName: string;
|
|
350
|
+
brandName: string;
|
|
351
|
+
totalQuantity: number;
|
|
352
|
+
totalRevenue: number;
|
|
353
|
+
usageCount: number;
|
|
354
|
+
}>;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Patient Analytics
|
|
359
|
+
* Comprehensive patient metrics
|
|
360
|
+
*/
|
|
361
|
+
export interface PatientAnalytics {
|
|
362
|
+
patientId: string;
|
|
363
|
+
patientName: string;
|
|
364
|
+
totalAppointments: number;
|
|
365
|
+
completedAppointments: number;
|
|
366
|
+
canceledAppointments: number;
|
|
367
|
+
noShowAppointments: number;
|
|
368
|
+
cancellationRate: number; // percentage
|
|
369
|
+
noShowRate: number; // percentage
|
|
370
|
+
totalRevenue: number;
|
|
371
|
+
averageRevenuePerAppointment: number;
|
|
372
|
+
currency: string;
|
|
373
|
+
lifetimeValue: number;
|
|
374
|
+
firstAppointmentDate: Date | null;
|
|
375
|
+
lastAppointmentDate: Date | null;
|
|
376
|
+
averageDaysBetweenAppointments: number | null;
|
|
377
|
+
uniquePractitioners: number;
|
|
378
|
+
uniqueClinics: number;
|
|
379
|
+
favoriteProcedures: Array<{
|
|
380
|
+
procedureId: string;
|
|
381
|
+
procedureName: string;
|
|
382
|
+
count: number;
|
|
383
|
+
}>;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Patient Lifetime Value Metrics
|
|
388
|
+
* Patient value analysis
|
|
389
|
+
*/
|
|
390
|
+
export interface PatientLifetimeValueMetrics {
|
|
391
|
+
totalPatients: number;
|
|
392
|
+
averageLifetimeValue: number;
|
|
393
|
+
currency: string;
|
|
394
|
+
topPatients: Array<{
|
|
395
|
+
patientId: string;
|
|
396
|
+
patientName: string;
|
|
397
|
+
lifetimeValue: number;
|
|
398
|
+
appointmentCount: number;
|
|
399
|
+
}>;
|
|
400
|
+
valueDistribution: Array<{
|
|
401
|
+
range: string; // e.g., "0-500", "500-1000", "1000+"
|
|
402
|
+
count: number;
|
|
403
|
+
percentage: number;
|
|
404
|
+
}>;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Patient Retention Metrics
|
|
409
|
+
* Patient retention and return analysis
|
|
410
|
+
*/
|
|
411
|
+
export interface PatientRetentionMetrics {
|
|
412
|
+
totalPatients: number;
|
|
413
|
+
newPatients: number;
|
|
414
|
+
returningPatients: number;
|
|
415
|
+
retentionRate: number; // percentage
|
|
416
|
+
averageAppointmentsPerPatient: number;
|
|
417
|
+
patientsByAppointmentCount: Array<{
|
|
418
|
+
appointmentCount: number;
|
|
419
|
+
patientCount: number;
|
|
420
|
+
percentage: number;
|
|
421
|
+
}>;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Cost Per Patient Metrics
|
|
426
|
+
* Cost analysis per patient
|
|
427
|
+
*/
|
|
428
|
+
export interface CostPerPatientMetrics {
|
|
429
|
+
totalPatients: number;
|
|
430
|
+
totalRevenue: number;
|
|
431
|
+
averageCostPerPatient: number;
|
|
432
|
+
currency: string;
|
|
433
|
+
costDistribution: Array<{
|
|
434
|
+
range: string;
|
|
435
|
+
patientCount: number;
|
|
436
|
+
percentage: number;
|
|
437
|
+
}>;
|
|
438
|
+
patientCosts?: Array<{
|
|
439
|
+
patientId: string;
|
|
440
|
+
patientName: string;
|
|
441
|
+
totalCost: number;
|
|
442
|
+
appointmentCount: number;
|
|
443
|
+
averageCost: number;
|
|
444
|
+
}>;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Payment Status Breakdown
|
|
449
|
+
* Analysis of payment statuses
|
|
450
|
+
*/
|
|
451
|
+
export interface PaymentStatusBreakdown {
|
|
452
|
+
totalAppointments: number;
|
|
453
|
+
byStatus: Partial<Record<PaymentStatus, {
|
|
454
|
+
count: number;
|
|
455
|
+
percentage: number;
|
|
456
|
+
totalRevenue: number;
|
|
457
|
+
}>>;
|
|
458
|
+
unpaidCount: number;
|
|
459
|
+
unpaidRevenue: number;
|
|
460
|
+
paidCount: number;
|
|
461
|
+
paidRevenue: number;
|
|
462
|
+
partiallyPaidCount: number;
|
|
463
|
+
partiallyPaidRevenue: number;
|
|
464
|
+
refundedCount: number;
|
|
465
|
+
refundedRevenue: number;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Clinic Analytics
|
|
470
|
+
* Comprehensive clinic performance metrics
|
|
471
|
+
*/
|
|
472
|
+
export interface ClinicAnalytics {
|
|
473
|
+
clinicBranchId: string;
|
|
474
|
+
clinicName: string;
|
|
475
|
+
totalAppointments: number;
|
|
476
|
+
completedAppointments: number;
|
|
477
|
+
canceledAppointments: number;
|
|
478
|
+
noShowAppointments: number;
|
|
479
|
+
cancellationRate: number; // percentage
|
|
480
|
+
noShowRate: number; // percentage
|
|
481
|
+
totalRevenue: number;
|
|
482
|
+
averageRevenuePerAppointment: number;
|
|
483
|
+
currency: string;
|
|
484
|
+
practitionerCount: number;
|
|
485
|
+
patientCount: number;
|
|
486
|
+
procedureCount: number;
|
|
487
|
+
topPractitioners: Array<{
|
|
488
|
+
practitionerId: string;
|
|
489
|
+
practitionerName: string;
|
|
490
|
+
appointmentCount: number;
|
|
491
|
+
revenue: number;
|
|
492
|
+
}>;
|
|
493
|
+
topProcedures: Array<{
|
|
494
|
+
procedureId: string;
|
|
495
|
+
procedureName: string;
|
|
496
|
+
appointmentCount: number;
|
|
497
|
+
revenue: number;
|
|
498
|
+
}>;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Clinic Comparison Metrics
|
|
503
|
+
* Comparison data for multiple clinics
|
|
504
|
+
*/
|
|
505
|
+
export interface ClinicComparisonMetrics {
|
|
506
|
+
clinicBranchId: string;
|
|
507
|
+
clinicName: string;
|
|
508
|
+
totalAppointments: number;
|
|
509
|
+
completedAppointments: number;
|
|
510
|
+
cancellationRate: number;
|
|
511
|
+
noShowRate: number;
|
|
512
|
+
totalRevenue: number;
|
|
513
|
+
averageRevenuePerAppointment: number;
|
|
514
|
+
practitionerCount: number;
|
|
515
|
+
patientCount: number;
|
|
516
|
+
efficiency: number; // percentage
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* Procedure Popularity
|
|
521
|
+
* Popularity metrics for procedures
|
|
522
|
+
*/
|
|
523
|
+
export interface ProcedurePopularity {
|
|
524
|
+
procedureId: string;
|
|
525
|
+
procedureName: string;
|
|
526
|
+
categoryName: string;
|
|
527
|
+
subcategoryName: string;
|
|
528
|
+
technologyName: string;
|
|
529
|
+
appointmentCount: number;
|
|
530
|
+
completedCount: number;
|
|
531
|
+
rank: number;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* Procedure Profitability
|
|
536
|
+
* Profitability metrics for procedures
|
|
537
|
+
*/
|
|
538
|
+
export interface ProcedureProfitability {
|
|
539
|
+
procedureId: string;
|
|
540
|
+
procedureName: string;
|
|
541
|
+
categoryName: string;
|
|
542
|
+
subcategoryName: string;
|
|
543
|
+
technologyName: string;
|
|
544
|
+
totalRevenue: number;
|
|
545
|
+
averageRevenue: number;
|
|
546
|
+
appointmentCount: number;
|
|
547
|
+
rank: number;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* Cancellation Reason Statistics
|
|
552
|
+
* Breakdown of cancellation reasons
|
|
553
|
+
*/
|
|
554
|
+
export interface CancellationReasonStats {
|
|
555
|
+
reason: string;
|
|
556
|
+
count: number;
|
|
557
|
+
percentage: number;
|
|
558
|
+
averageLeadTime: number; // hours
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* Dashboard Analytics
|
|
563
|
+
* Comprehensive dashboard data aggregation
|
|
564
|
+
*/
|
|
565
|
+
export interface DashboardAnalytics {
|
|
566
|
+
overview: {
|
|
567
|
+
totalAppointments: number;
|
|
568
|
+
completedAppointments: number;
|
|
569
|
+
canceledAppointments: number;
|
|
570
|
+
noShowAppointments: number;
|
|
571
|
+
pendingAppointments: number;
|
|
572
|
+
confirmedAppointments: number;
|
|
573
|
+
totalRevenue: number;
|
|
574
|
+
averageRevenuePerAppointment: number;
|
|
575
|
+
currency: string;
|
|
576
|
+
uniquePatients: number;
|
|
577
|
+
uniquePractitioners: number;
|
|
578
|
+
uniqueProcedures: number;
|
|
579
|
+
cancellationRate: number;
|
|
580
|
+
noShowRate: number;
|
|
581
|
+
};
|
|
582
|
+
practitionerMetrics: PractitionerAnalytics[];
|
|
583
|
+
procedureMetrics: ProcedureAnalytics[];
|
|
584
|
+
cancellationMetrics: CancellationMetrics;
|
|
585
|
+
noShowMetrics: NoShowMetrics;
|
|
586
|
+
revenueTrends: RevenueTrend[];
|
|
587
|
+
timeEfficiency: TimeEfficiencyMetrics;
|
|
588
|
+
topProducts: ProductUsageMetrics[];
|
|
589
|
+
recentActivity: Array<{
|
|
590
|
+
type: 'appointment' | 'cancellation' | 'completion' | 'no_show';
|
|
591
|
+
date: Date;
|
|
592
|
+
description: string;
|
|
593
|
+
entityId?: string;
|
|
594
|
+
entityName?: string;
|
|
595
|
+
}>;
|
|
596
|
+
}
|
|
597
|
+
|