@blackcode_sa/metaestetics-api 1.12.68 → 1.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/admin/index.d.mts +801 -2
  2. package/dist/admin/index.d.ts +801 -2
  3. package/dist/admin/index.js +2332 -153
  4. package/dist/admin/index.mjs +2321 -153
  5. package/dist/index.d.mts +1057 -2
  6. package/dist/index.d.ts +1057 -2
  7. package/dist/index.js +4150 -2117
  8. package/dist/index.mjs +3832 -1810
  9. package/package.json +1 -1
  10. package/src/admin/aggregation/appointment/appointment.aggregation.service.ts +140 -0
  11. package/src/admin/analytics/analytics.admin.service.ts +278 -0
  12. package/src/admin/analytics/index.ts +2 -0
  13. package/src/admin/index.ts +6 -0
  14. package/src/backoffice/services/README.md +17 -0
  15. package/src/backoffice/services/analytics.service.proposal.md +863 -0
  16. package/src/backoffice/services/analytics.service.summary.md +143 -0
  17. package/src/services/analytics/ARCHITECTURE.md +199 -0
  18. package/src/services/analytics/CLOUD_FUNCTIONS.md +225 -0
  19. package/src/services/analytics/GROUPED_ANALYTICS.md +501 -0
  20. package/src/services/analytics/QUICK_START.md +393 -0
  21. package/src/services/analytics/README.md +287 -0
  22. package/src/services/analytics/SUMMARY.md +141 -0
  23. package/src/services/analytics/USAGE_GUIDE.md +518 -0
  24. package/src/services/analytics/analytics-cloud.service.ts +222 -0
  25. package/src/services/analytics/analytics.service.ts +1632 -0
  26. package/src/services/analytics/index.ts +3 -0
  27. package/src/services/analytics/utils/appointment-filtering.utils.ts +138 -0
  28. package/src/services/analytics/utils/cost-calculation.utils.ts +154 -0
  29. package/src/services/analytics/utils/grouping.utils.ts +394 -0
  30. package/src/services/analytics/utils/stored-analytics.utils.ts +347 -0
  31. package/src/services/analytics/utils/time-calculation.utils.ts +186 -0
  32. package/src/services/appointment/appointment.service.ts +50 -6
  33. package/src/services/index.ts +1 -0
  34. package/src/types/analytics/analytics.types.ts +500 -0
  35. package/src/types/analytics/grouped-analytics.types.ts +148 -0
  36. package/src/types/analytics/index.ts +4 -0
  37. package/src/types/analytics/stored-analytics.types.ts +137 -0
  38. package/src/types/index.ts +3 -0
  39. package/src/types/notifications/index.ts +21 -0
@@ -0,0 +1,222 @@
1
+ import { Functions, getFunctions, httpsCallable } from 'firebase/functions';
2
+ import { FirebaseApp } from 'firebase/app';
3
+ import {
4
+ AnalyticsDateRange,
5
+ AnalyticsFilters,
6
+ EntityType,
7
+ } from '../../types/analytics';
8
+
9
+ /**
10
+ * Request data for on-demand analytics calculation
11
+ */
12
+ interface CalculateAnalyticsRequest {
13
+ analyticsType:
14
+ | 'dashboard'
15
+ | 'practitioner'
16
+ | 'procedure'
17
+ | 'clinic'
18
+ | 'timeEfficiency'
19
+ | 'revenue'
20
+ | 'cancellation'
21
+ | 'noShow'
22
+ | 'productUsage'
23
+ | 'patient'
24
+ | 'revenueByEntity'
25
+ | 'productUsageByEntity'
26
+ | 'timeEfficiencyByEntity'
27
+ | 'patientBehaviorByEntity';
28
+ filters?: AnalyticsFilters;
29
+ dateRange?: {
30
+ start: string; // ISO date string
31
+ end: string; // ISO date string
32
+ };
33
+ entityId?: string;
34
+ groupBy?: EntityType;
35
+ options?: {
36
+ storeInCache?: boolean;
37
+ useCache?: boolean;
38
+ maxCacheAgeHours?: number;
39
+ };
40
+ }
41
+
42
+ /**
43
+ * Response from on-demand analytics calculation
44
+ */
45
+ interface CalculateAnalyticsResponse {
46
+ success: boolean;
47
+ data: any;
48
+ computedAt: string;
49
+ }
50
+
51
+ /**
52
+ * Client-side service for calling analytics Cloud Functions
53
+ *
54
+ * This service provides a convenient way to trigger on-demand analytics
55
+ * calculations via Cloud Functions, which can be faster and more efficient
56
+ * than calculating on the client.
57
+ */
58
+ export class AnalyticsCloudService {
59
+ private functions: Functions;
60
+
61
+ /**
62
+ * Creates a new AnalyticsCloudService instance
63
+ *
64
+ * @param app - Firebase App instance
65
+ * @param region - Functions region (default: 'europe-west6')
66
+ */
67
+ constructor(app: FirebaseApp, region: string = 'europe-west6') {
68
+ this.functions = getFunctions(app, region);
69
+ }
70
+
71
+ /**
72
+ * Calls the Cloud Function to calculate analytics on-demand
73
+ *
74
+ * @param request - Analytics calculation request
75
+ * @returns Promise resolving to the calculated analytics data
76
+ */
77
+ async calculateOnDemand(request: CalculateAnalyticsRequest): Promise<any> {
78
+ const callable = httpsCallable<CalculateAnalyticsRequest, CalculateAnalyticsResponse>(
79
+ this.functions,
80
+ 'calculateAnalyticsOnDemand',
81
+ );
82
+
83
+ const response = await callable(request);
84
+
85
+ if (!response.data.success) {
86
+ throw new Error('Analytics calculation failed');
87
+ }
88
+
89
+ return response.data.data;
90
+ }
91
+
92
+ /**
93
+ * Calculate dashboard analytics on-demand
94
+ */
95
+ async calculateDashboard(
96
+ filters: AnalyticsFilters,
97
+ dateRange: AnalyticsDateRange,
98
+ options?: { storeInCache?: boolean },
99
+ ) {
100
+ return this.calculateOnDemand({
101
+ analyticsType: 'dashboard',
102
+ filters,
103
+ dateRange: {
104
+ start: dateRange.start.toISOString(),
105
+ end: dateRange.end.toISOString(),
106
+ },
107
+ options,
108
+ });
109
+ }
110
+
111
+ /**
112
+ * Calculate practitioner analytics on-demand
113
+ */
114
+ async calculatePractitioner(
115
+ practitionerId: string,
116
+ dateRange?: AnalyticsDateRange,
117
+ options?: { storeInCache?: boolean; clinicBranchId?: string },
118
+ ) {
119
+ return this.calculateOnDemand({
120
+ analyticsType: 'practitioner',
121
+ entityId: practitionerId,
122
+ filters: options?.clinicBranchId ? { clinicBranchId: options.clinicBranchId } : undefined,
123
+ dateRange: dateRange
124
+ ? {
125
+ start: dateRange.start.toISOString(),
126
+ end: dateRange.end.toISOString(),
127
+ }
128
+ : undefined,
129
+ options,
130
+ });
131
+ }
132
+
133
+ /**
134
+ * Calculate procedure analytics on-demand
135
+ */
136
+ async calculateProcedure(
137
+ procedureId: string,
138
+ dateRange?: AnalyticsDateRange,
139
+ options?: { storeInCache?: boolean; clinicBranchId?: string },
140
+ ) {
141
+ return this.calculateOnDemand({
142
+ analyticsType: 'procedure',
143
+ entityId: procedureId,
144
+ filters: options?.clinicBranchId ? { clinicBranchId: options.clinicBranchId } : undefined,
145
+ dateRange: dateRange
146
+ ? {
147
+ start: dateRange.start.toISOString(),
148
+ end: dateRange.end.toISOString(),
149
+ }
150
+ : undefined,
151
+ options,
152
+ });
153
+ }
154
+
155
+ /**
156
+ * Calculate revenue metrics grouped by entity on-demand
157
+ */
158
+ async calculateRevenueByEntity(
159
+ groupBy: EntityType,
160
+ dateRange?: AnalyticsDateRange,
161
+ filters?: AnalyticsFilters,
162
+ options?: { storeInCache?: boolean },
163
+ ) {
164
+ return this.calculateOnDemand({
165
+ analyticsType: 'revenueByEntity',
166
+ groupBy,
167
+ filters,
168
+ dateRange: dateRange
169
+ ? {
170
+ start: dateRange.start.toISOString(),
171
+ end: dateRange.end.toISOString(),
172
+ }
173
+ : undefined,
174
+ options,
175
+ });
176
+ }
177
+
178
+ /**
179
+ * Calculate cancellation metrics grouped by entity on-demand
180
+ */
181
+ async calculateCancellations(
182
+ groupBy: EntityType,
183
+ dateRange?: AnalyticsDateRange,
184
+ options?: { storeInCache?: boolean; clinicBranchId?: string },
185
+ ) {
186
+ return this.calculateOnDemand({
187
+ analyticsType: 'cancellation',
188
+ groupBy,
189
+ filters: options?.clinicBranchId ? { clinicBranchId: options.clinicBranchId } : undefined,
190
+ dateRange: dateRange
191
+ ? {
192
+ start: dateRange.start.toISOString(),
193
+ end: dateRange.end.toISOString(),
194
+ }
195
+ : undefined,
196
+ options,
197
+ });
198
+ }
199
+
200
+ /**
201
+ * Calculate no-show metrics grouped by entity on-demand
202
+ */
203
+ async calculateNoShows(
204
+ groupBy: EntityType,
205
+ dateRange?: AnalyticsDateRange,
206
+ options?: { storeInCache?: boolean; clinicBranchId?: string },
207
+ ) {
208
+ return this.calculateOnDemand({
209
+ analyticsType: 'noShow',
210
+ groupBy,
211
+ filters: options?.clinicBranchId ? { clinicBranchId: options.clinicBranchId } : undefined,
212
+ dateRange: dateRange
213
+ ? {
214
+ start: dateRange.start.toISOString(),
215
+ end: dateRange.end.toISOString(),
216
+ }
217
+ : undefined,
218
+ options,
219
+ });
220
+ }
221
+ }
222
+