@blackcode_sa/metaestetics-api 1.12.20 → 1.12.21
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 +13 -3
- package/dist/admin/index.d.ts +13 -3
- package/dist/admin/index.js +194 -180
- package/dist/admin/index.mjs +194 -180
- package/dist/index.d.mts +51 -7
- package/dist/index.d.ts +51 -7
- package/dist/index.js +2087 -1888
- package/dist/index.mjs +2158 -1959
- package/package.json +1 -1
- package/src/admin/aggregation/appointment/appointment.aggregation.service.ts +459 -457
- package/src/services/appointment/appointment.service.ts +297 -0
- package/src/services/reviews/reviews.service.ts +30 -71
- package/src/types/appointment/index.ts +11 -0
- package/src/types/reviews/index.ts +0 -3
- package/src/validations/appointment.schema.ts +38 -18
package/dist/admin/index.mjs
CHANGED
|
@@ -2017,9 +2017,7 @@ var AppointmentAggregationService = class {
|
|
|
2017
2017
|
);
|
|
2018
2018
|
this.notificationsAdmin = new NotificationsAdmin(this.db);
|
|
2019
2019
|
this.calendarAdminService = new CalendarAdminService(this.db);
|
|
2020
|
-
this.patientRequirementsAdminService = new PatientRequirementsAdminService(
|
|
2021
|
-
this.db
|
|
2022
|
-
);
|
|
2020
|
+
this.patientRequirementsAdminService = new PatientRequirementsAdminService(this.db);
|
|
2023
2021
|
Logger.info("[AppointmentAggregationService] Initialized.");
|
|
2024
2022
|
}
|
|
2025
2023
|
/**
|
|
@@ -2034,12 +2032,7 @@ var AppointmentAggregationService = class {
|
|
|
2034
2032
|
`[AggService] Handling CREATE for appointment: ${appointment.id}, patient: ${appointment.patientId}, status: ${appointment.status}`
|
|
2035
2033
|
);
|
|
2036
2034
|
try {
|
|
2037
|
-
const [
|
|
2038
|
-
patientProfile,
|
|
2039
|
-
patientSensitiveInfo,
|
|
2040
|
-
practitionerProfile,
|
|
2041
|
-
clinicInfo
|
|
2042
|
-
] = await Promise.all([
|
|
2035
|
+
const [patientProfile, patientSensitiveInfo, practitionerProfile, clinicInfo] = await Promise.all([
|
|
2043
2036
|
this.fetchPatientProfile(appointment.patientId),
|
|
2044
2037
|
this.fetchPatientSensitiveInfo(appointment.patientId),
|
|
2045
2038
|
this.fetchPractitionerProfile(appointment.practitionerId),
|
|
@@ -2056,9 +2049,7 @@ var AppointmentAggregationService = class {
|
|
|
2056
2049
|
);
|
|
2057
2050
|
}
|
|
2058
2051
|
if (appointment.status === "confirmed" /* CONFIRMED */) {
|
|
2059
|
-
Logger.info(
|
|
2060
|
-
`[AggService] Appt ${appointment.id} created as CONFIRMED.`
|
|
2061
|
-
);
|
|
2052
|
+
Logger.info(`[AggService] Appt ${appointment.id} created as CONFIRMED.`);
|
|
2062
2053
|
await this.createPreAppointmentRequirementInstances(appointment);
|
|
2063
2054
|
if ((patientSensitiveInfo == null ? void 0 : patientSensitiveInfo.email) && patientProfile) {
|
|
2064
2055
|
Logger.info(
|
|
@@ -2126,9 +2117,7 @@ var AppointmentAggregationService = class {
|
|
|
2126
2117
|
);
|
|
2127
2118
|
}
|
|
2128
2119
|
}
|
|
2129
|
-
Logger.info(
|
|
2130
|
-
`[AggService] Successfully processed CREATE for appointment: ${appointment.id}`
|
|
2131
|
-
);
|
|
2120
|
+
Logger.info(`[AggService] Successfully processed CREATE for appointment: ${appointment.id}`);
|
|
2132
2121
|
} catch (error) {
|
|
2133
2122
|
Logger.error(
|
|
2134
2123
|
`[AggService] Critical error in handleAppointmentCreate for appointment ${appointment.id}:`,
|
|
@@ -2151,12 +2140,8 @@ var AppointmentAggregationService = class {
|
|
|
2151
2140
|
try {
|
|
2152
2141
|
const statusChanged = before.status !== after.status;
|
|
2153
2142
|
const timeChanged = before.appointmentStartTime.toMillis() !== after.appointmentStartTime.toMillis() || before.appointmentEndTime.toMillis() !== after.appointmentEndTime.toMillis();
|
|
2154
|
-
const
|
|
2155
|
-
|
|
2156
|
-
patientSensitiveInfo,
|
|
2157
|
-
practitionerProfile,
|
|
2158
|
-
clinicInfo
|
|
2159
|
-
] = await Promise.all([
|
|
2143
|
+
const zonePhotosChanged = this.hasZonePhotosChanged(before, after);
|
|
2144
|
+
const [patientProfile, patientSensitiveInfo, practitionerProfile, clinicInfo] = await Promise.all([
|
|
2160
2145
|
this.fetchPatientProfile(after.patientId),
|
|
2161
2146
|
this.fetchPatientSensitiveInfo(after.patientId),
|
|
2162
2147
|
this.fetchPractitionerProfile(after.practitionerId),
|
|
@@ -2182,9 +2167,7 @@ var AppointmentAggregationService = class {
|
|
|
2182
2167
|
recipientProfile: after.patientInfo,
|
|
2183
2168
|
recipientRole: "patient"
|
|
2184
2169
|
};
|
|
2185
|
-
await this.appointmentMailingService.sendAppointmentConfirmedEmail(
|
|
2186
|
-
emailData
|
|
2187
|
-
);
|
|
2170
|
+
await this.appointmentMailingService.sendAppointmentConfirmedEmail(emailData);
|
|
2188
2171
|
} else {
|
|
2189
2172
|
Logger.warn(
|
|
2190
2173
|
`[AggService] Cannot send confirmation email to patient ${after.patientId}: email missing.`
|
|
@@ -2215,9 +2198,7 @@ var AppointmentAggregationService = class {
|
|
|
2215
2198
|
);
|
|
2216
2199
|
}
|
|
2217
2200
|
} else if (before.status === "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */ && after.status === "confirmed" /* CONFIRMED */) {
|
|
2218
|
-
Logger.info(
|
|
2219
|
-
`[AggService] Appt ${after.id} RESCHEDULED_BY_CLINIC -> CONFIRMED.`
|
|
2220
|
-
);
|
|
2201
|
+
Logger.info(`[AggService] Appt ${after.id} RESCHEDULED_BY_CLINIC -> CONFIRMED.`);
|
|
2221
2202
|
await this.updateRelatedPatientRequirementInstances(
|
|
2222
2203
|
before,
|
|
2223
2204
|
"supersededReschedule" /* SUPERSEDED_RESCHEDULE */
|
|
@@ -2236,9 +2217,7 @@ var AppointmentAggregationService = class {
|
|
|
2236
2217
|
recipientProfile: after.patientInfo,
|
|
2237
2218
|
recipientRole: "patient"
|
|
2238
2219
|
};
|
|
2239
|
-
await this.appointmentMailingService.sendAppointmentConfirmedEmail(
|
|
2240
|
-
emailData
|
|
2241
|
-
);
|
|
2220
|
+
await this.appointmentMailingService.sendAppointmentConfirmedEmail(emailData);
|
|
2242
2221
|
}
|
|
2243
2222
|
if ((patientProfile == null ? void 0 : patientProfile.expoTokens) && patientProfile.expoTokens.length > 0) {
|
|
2244
2223
|
await this.notificationsAdmin.sendAppointmentConfirmedPush(
|
|
@@ -2349,21 +2328,16 @@ var AppointmentAggregationService = class {
|
|
|
2349
2328
|
);
|
|
2350
2329
|
}
|
|
2351
2330
|
} else if (after.status === "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */) {
|
|
2352
|
-
Logger.info(
|
|
2353
|
-
`[AggService] Appt ${after.id} status -> RESCHEDULED_BY_CLINIC.`
|
|
2354
|
-
);
|
|
2331
|
+
Logger.info(`[AggService] Appt ${after.id} status -> RESCHEDULED_BY_CLINIC.`);
|
|
2355
2332
|
await this.updateRelatedPatientRequirementInstances(
|
|
2356
2333
|
before,
|
|
2357
2334
|
// Pass the 'before' state for old requirements
|
|
2358
2335
|
"supersededReschedule" /* SUPERSEDED_RESCHEDULE */
|
|
2359
2336
|
);
|
|
2360
|
-
await this.calendarAdminService.updateAppointmentCalendarEventsTime(
|
|
2361
|
-
after,
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
end: after.appointmentEndTime
|
|
2365
|
-
}
|
|
2366
|
-
);
|
|
2337
|
+
await this.calendarAdminService.updateAppointmentCalendarEventsTime(after, {
|
|
2338
|
+
start: after.appointmentStartTime,
|
|
2339
|
+
end: after.appointmentEndTime
|
|
2340
|
+
});
|
|
2367
2341
|
await this.calendarAdminService.updateAppointmentCalendarEventsStatus(
|
|
2368
2342
|
after,
|
|
2369
2343
|
"pending" /* PENDING */
|
|
@@ -2397,22 +2371,21 @@ var AppointmentAggregationService = class {
|
|
|
2397
2371
|
"supersededReschedule" /* SUPERSEDED_RESCHEDULE */
|
|
2398
2372
|
);
|
|
2399
2373
|
await this.createPreAppointmentRequirementInstances(after);
|
|
2400
|
-
await this.calendarAdminService.updateAppointmentCalendarEventsTime(
|
|
2401
|
-
after,
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
end: after.appointmentEndTime
|
|
2405
|
-
}
|
|
2406
|
-
);
|
|
2374
|
+
await this.calendarAdminService.updateAppointmentCalendarEventsTime(after, {
|
|
2375
|
+
start: after.appointmentStartTime,
|
|
2376
|
+
end: after.appointmentEndTime
|
|
2377
|
+
});
|
|
2407
2378
|
} else {
|
|
2408
2379
|
Logger.warn(
|
|
2409
2380
|
`[AggService] Independent time change detected for ${after.id} with status ${after.status}. Review implications for requirements and calendar.`
|
|
2410
2381
|
);
|
|
2411
2382
|
}
|
|
2412
2383
|
}
|
|
2413
|
-
|
|
2414
|
-
`[AggService]
|
|
2415
|
-
|
|
2384
|
+
if (zonePhotosChanged) {
|
|
2385
|
+
Logger.info(`[AggService] Zone photos changed for appointment ${after.id}`);
|
|
2386
|
+
await this.handleZonePhotosUpdate(before, after);
|
|
2387
|
+
}
|
|
2388
|
+
Logger.info(`[AggService] Successfully processed UPDATE for appointment: ${after.id}`);
|
|
2416
2389
|
} catch (error) {
|
|
2417
2390
|
Logger.error(
|
|
2418
2391
|
`[AggService] Critical error in handleAppointmentUpdate for appointment ${after.id}:`,
|
|
@@ -2426,16 +2399,12 @@ var AppointmentAggregationService = class {
|
|
|
2426
2399
|
* @returns {Promise<void>}
|
|
2427
2400
|
*/
|
|
2428
2401
|
async handleAppointmentDelete(deletedAppointment) {
|
|
2429
|
-
Logger.info(
|
|
2430
|
-
`[AggService] Handling DELETE for appointment: ${deletedAppointment.id}`
|
|
2431
|
-
);
|
|
2402
|
+
Logger.info(`[AggService] Handling DELETE for appointment: ${deletedAppointment.id}`);
|
|
2432
2403
|
await this.updateRelatedPatientRequirementInstances(
|
|
2433
2404
|
deletedAppointment,
|
|
2434
2405
|
"cancelledAppointment" /* CANCELLED_APPOINTMENT */
|
|
2435
2406
|
);
|
|
2436
|
-
const patientProfile = await this.fetchPatientProfile(
|
|
2437
|
-
deletedAppointment.patientId
|
|
2438
|
-
);
|
|
2407
|
+
const patientProfile = await this.fetchPatientProfile(deletedAppointment.patientId);
|
|
2439
2408
|
if (patientProfile) {
|
|
2440
2409
|
await this.managePatientClinicPractitionerLinks(
|
|
2441
2410
|
patientProfile,
|
|
@@ -2444,9 +2413,7 @@ var AppointmentAggregationService = class {
|
|
|
2444
2413
|
"cancel"
|
|
2445
2414
|
);
|
|
2446
2415
|
}
|
|
2447
|
-
await this.calendarAdminService.deleteAppointmentCalendarEvents(
|
|
2448
|
-
deletedAppointment
|
|
2449
|
-
);
|
|
2416
|
+
await this.calendarAdminService.deleteAppointmentCalendarEvents(deletedAppointment);
|
|
2450
2417
|
}
|
|
2451
2418
|
// --- Helper Methods for Aggregation Logic ---
|
|
2452
2419
|
/**
|
|
@@ -2516,15 +2483,11 @@ var AppointmentAggregationService = class {
|
|
|
2516
2483
|
`[AggService] Processing template ${template.id} (${template.name}) for appt ${appointment.id}`
|
|
2517
2484
|
);
|
|
2518
2485
|
const newInstanceRef = this.db.collection(PATIENTS_COLLECTION).doc(appointment.patientId).collection(PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME).doc();
|
|
2519
|
-
Logger.debug(
|
|
2520
|
-
`[AggService] Created doc reference: ${newInstanceRef.path}`
|
|
2521
|
-
);
|
|
2486
|
+
Logger.debug(`[AggService] Created doc reference: ${newInstanceRef.path}`);
|
|
2522
2487
|
const instructions = (((_a = template.timeframe) == null ? void 0 : _a.notifyAt) || []).map((notifyAtValue) => {
|
|
2523
2488
|
let dueTime = appointment.appointmentStartTime;
|
|
2524
2489
|
if (template.timeframe && typeof notifyAtValue === "number") {
|
|
2525
|
-
const dueDateTime = new Date(
|
|
2526
|
-
appointment.appointmentStartTime.toMillis()
|
|
2527
|
-
);
|
|
2490
|
+
const dueDateTime = new Date(appointment.appointmentStartTime.toMillis());
|
|
2528
2491
|
if (template.timeframe.unit === "days" /* DAYS */) {
|
|
2529
2492
|
dueDateTime.setDate(dueDateTime.getDate() - notifyAtValue);
|
|
2530
2493
|
} else if (template.timeframe.unit === "hours" /* HOURS */) {
|
|
@@ -2598,26 +2561,20 @@ var AppointmentAggregationService = class {
|
|
|
2598
2561
|
Logger.warn(
|
|
2599
2562
|
`[AggService] Batch commit reported success but documents not found! Attempting direct creation as fallback...`
|
|
2600
2563
|
);
|
|
2601
|
-
const fallbackPromises = createdInstances.map(
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
fallbackError
|
|
2613
|
-
);
|
|
2614
|
-
return false;
|
|
2615
|
-
}
|
|
2564
|
+
const fallbackPromises = createdInstances.map(async ({ ref, data }) => {
|
|
2565
|
+
try {
|
|
2566
|
+
await ref.set(data);
|
|
2567
|
+
Logger.info(`[AggService] Fallback direct creation success for ${ref.id}`);
|
|
2568
|
+
return true;
|
|
2569
|
+
} catch (fallbackError) {
|
|
2570
|
+
Logger.error(
|
|
2571
|
+
`[AggService] Fallback direct creation failed for ${ref.id}:`,
|
|
2572
|
+
fallbackError
|
|
2573
|
+
);
|
|
2574
|
+
return false;
|
|
2616
2575
|
}
|
|
2617
|
-
);
|
|
2618
|
-
const fallbackResults = await Promise.allSettled(
|
|
2619
|
-
fallbackPromises
|
|
2620
|
-
);
|
|
2576
|
+
});
|
|
2577
|
+
const fallbackResults = await Promise.allSettled(fallbackPromises);
|
|
2621
2578
|
const successCount = fallbackResults.filter(
|
|
2622
2579
|
(r) => r.status === "fulfilled" && r.value === true
|
|
2623
2580
|
).length;
|
|
@@ -2650,23 +2607,19 @@ var AppointmentAggregationService = class {
|
|
|
2650
2607
|
commitError
|
|
2651
2608
|
);
|
|
2652
2609
|
Logger.info(`[AggService] Attempting direct creation as fallback...`);
|
|
2653
|
-
const fallbackPromises = createdInstances.map(
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
fallbackError
|
|
2665
|
-
);
|
|
2666
|
-
return false;
|
|
2667
|
-
}
|
|
2610
|
+
const fallbackPromises = createdInstances.map(async ({ ref, data }) => {
|
|
2611
|
+
try {
|
|
2612
|
+
await ref.set(data);
|
|
2613
|
+
Logger.info(`[AggService] Fallback direct creation success for ${ref.id}`);
|
|
2614
|
+
return true;
|
|
2615
|
+
} catch (fallbackError) {
|
|
2616
|
+
Logger.error(
|
|
2617
|
+
`[AggService] Fallback direct creation failed for ${ref.id}:`,
|
|
2618
|
+
fallbackError
|
|
2619
|
+
);
|
|
2620
|
+
return false;
|
|
2668
2621
|
}
|
|
2669
|
-
);
|
|
2622
|
+
});
|
|
2670
2623
|
const fallbackResults = await Promise.allSettled(fallbackPromises);
|
|
2671
2624
|
const successCount = fallbackResults.filter(
|
|
2672
2625
|
(r) => r.status === "fulfilled" && r.value === true
|
|
@@ -2764,15 +2717,11 @@ var AppointmentAggregationService = class {
|
|
|
2764
2717
|
`[AggService] Processing template ${template.id} (${template.name}) for appt ${appointment.id}`
|
|
2765
2718
|
);
|
|
2766
2719
|
const newInstanceRef = this.db.collection(PATIENTS_COLLECTION).doc(appointment.patientId).collection(PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME).doc();
|
|
2767
|
-
Logger.debug(
|
|
2768
|
-
`[AggService] Created doc reference: ${newInstanceRef.path}`
|
|
2769
|
-
);
|
|
2720
|
+
Logger.debug(`[AggService] Created doc reference: ${newInstanceRef.path}`);
|
|
2770
2721
|
const instructions = (((_a = template.timeframe) == null ? void 0 : _a.notifyAt) || []).map((notifyAtValue) => {
|
|
2771
2722
|
let dueTime = appointment.appointmentEndTime;
|
|
2772
2723
|
if (template.timeframe && typeof notifyAtValue === "number") {
|
|
2773
|
-
const dueDateTime = new Date(
|
|
2774
|
-
appointment.appointmentEndTime.toMillis()
|
|
2775
|
-
);
|
|
2724
|
+
const dueDateTime = new Date(appointment.appointmentEndTime.toMillis());
|
|
2776
2725
|
if (template.timeframe.unit === "days" /* DAYS */) {
|
|
2777
2726
|
dueDateTime.setDate(dueDateTime.getDate() + notifyAtValue);
|
|
2778
2727
|
} else if (template.timeframe.unit === "hours" /* HOURS */) {
|
|
@@ -2843,26 +2792,20 @@ var AppointmentAggregationService = class {
|
|
|
2843
2792
|
Logger.warn(
|
|
2844
2793
|
`[AggService] Batch commit reported success but documents not found! Attempting direct creation as fallback...`
|
|
2845
2794
|
);
|
|
2846
|
-
const fallbackPromises = createdInstances.map(
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
fallbackError
|
|
2858
|
-
);
|
|
2859
|
-
return false;
|
|
2860
|
-
}
|
|
2795
|
+
const fallbackPromises = createdInstances.map(async ({ ref, data }) => {
|
|
2796
|
+
try {
|
|
2797
|
+
await ref.set(data);
|
|
2798
|
+
Logger.info(`[AggService] Fallback direct creation success for ${ref.id}`);
|
|
2799
|
+
return true;
|
|
2800
|
+
} catch (fallbackError) {
|
|
2801
|
+
Logger.error(
|
|
2802
|
+
`[AggService] Fallback direct creation failed for ${ref.id}:`,
|
|
2803
|
+
fallbackError
|
|
2804
|
+
);
|
|
2805
|
+
return false;
|
|
2861
2806
|
}
|
|
2862
|
-
);
|
|
2863
|
-
const fallbackResults = await Promise.allSettled(
|
|
2864
|
-
fallbackPromises
|
|
2865
|
-
);
|
|
2807
|
+
});
|
|
2808
|
+
const fallbackResults = await Promise.allSettled(fallbackPromises);
|
|
2866
2809
|
const successCount = fallbackResults.filter(
|
|
2867
2810
|
(r) => r.status === "fulfilled" && r.value === true
|
|
2868
2811
|
).length;
|
|
@@ -2895,23 +2838,19 @@ var AppointmentAggregationService = class {
|
|
|
2895
2838
|
commitError
|
|
2896
2839
|
);
|
|
2897
2840
|
Logger.info(`[AggService] Attempting direct creation as fallback...`);
|
|
2898
|
-
const fallbackPromises = createdInstances.map(
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
fallbackError
|
|
2910
|
-
);
|
|
2911
|
-
return false;
|
|
2912
|
-
}
|
|
2841
|
+
const fallbackPromises = createdInstances.map(async ({ ref, data }) => {
|
|
2842
|
+
try {
|
|
2843
|
+
await ref.set(data);
|
|
2844
|
+
Logger.info(`[AggService] Fallback direct creation success for ${ref.id}`);
|
|
2845
|
+
return true;
|
|
2846
|
+
} catch (fallbackError) {
|
|
2847
|
+
Logger.error(
|
|
2848
|
+
`[AggService] Fallback direct creation failed for ${ref.id}:`,
|
|
2849
|
+
fallbackError
|
|
2850
|
+
);
|
|
2851
|
+
return false;
|
|
2913
2852
|
}
|
|
2914
|
-
);
|
|
2853
|
+
});
|
|
2915
2854
|
const fallbackResults = await Promise.allSettled(fallbackPromises);
|
|
2916
2855
|
const successCount = fallbackResults.filter(
|
|
2917
2856
|
(r) => r.status === "fulfilled" && r.value === true
|
|
@@ -3061,9 +3000,7 @@ var AppointmentAggregationService = class {
|
|
|
3061
3000
|
updateData.doctorIds = admin6.firestore.FieldValue.arrayUnion(practitionerId);
|
|
3062
3001
|
}
|
|
3063
3002
|
if (!hasClinic) {
|
|
3064
|
-
Logger.debug(
|
|
3065
|
-
`[AggService] Adding clinic ${clinicId} to patient ${patientProfile.id}`
|
|
3066
|
-
);
|
|
3003
|
+
Logger.debug(`[AggService] Adding clinic ${clinicId} to patient ${patientProfile.id}`);
|
|
3067
3004
|
updateData.clinicIds = admin6.firestore.FieldValue.arrayUnion(clinicId);
|
|
3068
3005
|
}
|
|
3069
3006
|
await patientRef.update(updateData);
|
|
@@ -3118,28 +3055,19 @@ var AppointmentAggregationService = class {
|
|
|
3118
3055
|
updateNeeded = true;
|
|
3119
3056
|
}
|
|
3120
3057
|
if (activeClinicAppointments === 0 && ((_b = patientProfile.clinicIds) == null ? void 0 : _b.includes(clinicId))) {
|
|
3121
|
-
Logger.debug(
|
|
3122
|
-
`[AggService] Removing clinic ${clinicId} from patient ${patientProfile.id}`
|
|
3123
|
-
);
|
|
3058
|
+
Logger.debug(`[AggService] Removing clinic ${clinicId} from patient ${patientProfile.id}`);
|
|
3124
3059
|
updateData.clinicIds = admin6.firestore.FieldValue.arrayRemove(clinicId);
|
|
3125
3060
|
updateNeeded = true;
|
|
3126
3061
|
}
|
|
3127
3062
|
if (updateNeeded) {
|
|
3128
3063
|
updateData.updatedAt = admin6.firestore.FieldValue.serverTimestamp();
|
|
3129
3064
|
await patientRef.update(updateData);
|
|
3130
|
-
Logger.info(
|
|
3131
|
-
`[AggService] Successfully removed links from patient ${patientProfile.id}`
|
|
3132
|
-
);
|
|
3065
|
+
Logger.info(`[AggService] Successfully removed links from patient ${patientProfile.id}`);
|
|
3133
3066
|
} else {
|
|
3134
|
-
Logger.info(
|
|
3135
|
-
`[AggService] No links need to be removed from patient ${patientProfile.id}`
|
|
3136
|
-
);
|
|
3067
|
+
Logger.info(`[AggService] No links need to be removed from patient ${patientProfile.id}`);
|
|
3137
3068
|
}
|
|
3138
3069
|
} catch (error) {
|
|
3139
|
-
Logger.error(
|
|
3140
|
-
`[AggService] Error removing links from patient profile:`,
|
|
3141
|
-
error
|
|
3142
|
-
);
|
|
3070
|
+
Logger.error(`[AggService] Error removing links from patient profile:`, error);
|
|
3143
3071
|
throw error;
|
|
3144
3072
|
}
|
|
3145
3073
|
}
|
|
@@ -3172,10 +3100,7 @@ var AppointmentAggregationService = class {
|
|
|
3172
3100
|
const doc = await this.db.collection(PATIENTS_COLLECTION).doc(patientId).get();
|
|
3173
3101
|
return doc.exists ? doc.data() : null;
|
|
3174
3102
|
} catch (error) {
|
|
3175
|
-
Logger.error(
|
|
3176
|
-
`[AggService] Error fetching patient profile ${patientId}:`,
|
|
3177
|
-
error
|
|
3178
|
-
);
|
|
3103
|
+
Logger.error(`[AggService] Error fetching patient profile ${patientId}:`, error);
|
|
3179
3104
|
return null;
|
|
3180
3105
|
}
|
|
3181
3106
|
}
|
|
@@ -3188,17 +3113,12 @@ var AppointmentAggregationService = class {
|
|
|
3188
3113
|
try {
|
|
3189
3114
|
const doc = await this.db.collection(PATIENTS_COLLECTION).doc(patientId).collection(PATIENT_SENSITIVE_INFO_COLLECTION).doc(patientId).get();
|
|
3190
3115
|
if (!doc.exists) {
|
|
3191
|
-
Logger.warn(
|
|
3192
|
-
`[AggService] No sensitive info found for patient ${patientId}`
|
|
3193
|
-
);
|
|
3116
|
+
Logger.warn(`[AggService] No sensitive info found for patient ${patientId}`);
|
|
3194
3117
|
return null;
|
|
3195
3118
|
}
|
|
3196
3119
|
return doc.data();
|
|
3197
3120
|
} catch (error) {
|
|
3198
|
-
Logger.error(
|
|
3199
|
-
`[AggService] Error fetching patient sensitive info ${patientId}:`,
|
|
3200
|
-
error
|
|
3201
|
-
);
|
|
3121
|
+
Logger.error(`[AggService] Error fetching patient sensitive info ${patientId}:`, error);
|
|
3202
3122
|
return null;
|
|
3203
3123
|
}
|
|
3204
3124
|
}
|
|
@@ -3209,25 +3129,18 @@ var AppointmentAggregationService = class {
|
|
|
3209
3129
|
*/
|
|
3210
3130
|
async fetchPractitionerProfile(practitionerId) {
|
|
3211
3131
|
if (!practitionerId) {
|
|
3212
|
-
Logger.warn(
|
|
3213
|
-
"[AggService] fetchPractitionerProfile called with no practitionerId."
|
|
3214
|
-
);
|
|
3132
|
+
Logger.warn("[AggService] fetchPractitionerProfile called with no practitionerId.");
|
|
3215
3133
|
return null;
|
|
3216
3134
|
}
|
|
3217
3135
|
try {
|
|
3218
3136
|
const doc = await this.db.collection(PRACTITIONERS_COLLECTION).doc(practitionerId).get();
|
|
3219
3137
|
if (!doc.exists) {
|
|
3220
|
-
Logger.warn(
|
|
3221
|
-
`[AggService] No practitioner profile found for ID ${practitionerId}`
|
|
3222
|
-
);
|
|
3138
|
+
Logger.warn(`[AggService] No practitioner profile found for ID ${practitionerId}`);
|
|
3223
3139
|
return null;
|
|
3224
3140
|
}
|
|
3225
3141
|
return doc.data();
|
|
3226
3142
|
} catch (error) {
|
|
3227
|
-
Logger.error(
|
|
3228
|
-
`[AggService] Error fetching practitioner profile ${practitionerId}:`,
|
|
3229
|
-
error
|
|
3230
|
-
);
|
|
3143
|
+
Logger.error(`[AggService] Error fetching practitioner profile ${practitionerId}:`, error);
|
|
3231
3144
|
return null;
|
|
3232
3145
|
}
|
|
3233
3146
|
}
|
|
@@ -3248,12 +3161,113 @@ var AppointmentAggregationService = class {
|
|
|
3248
3161
|
return null;
|
|
3249
3162
|
}
|
|
3250
3163
|
return doc.data();
|
|
3164
|
+
} catch (error) {
|
|
3165
|
+
Logger.error(`[AggService] Error fetching clinic info ${clinicId}:`, error);
|
|
3166
|
+
return null;
|
|
3167
|
+
}
|
|
3168
|
+
}
|
|
3169
|
+
/**
|
|
3170
|
+
* Checks if zone photos have changed between two appointment states
|
|
3171
|
+
* @param before - The appointment state before update
|
|
3172
|
+
* @param after - The appointment state after update
|
|
3173
|
+
* @returns True if zone photos have changed, false otherwise
|
|
3174
|
+
*/
|
|
3175
|
+
hasZonePhotosChanged(before, after) {
|
|
3176
|
+
var _a, _b;
|
|
3177
|
+
const beforePhotos = (_a = before.metadata) == null ? void 0 : _a.zonePhotos;
|
|
3178
|
+
const afterPhotos = (_b = after.metadata) == null ? void 0 : _b.zonePhotos;
|
|
3179
|
+
if (!beforePhotos && !afterPhotos) {
|
|
3180
|
+
return false;
|
|
3181
|
+
}
|
|
3182
|
+
if (!beforePhotos || !afterPhotos) {
|
|
3183
|
+
return true;
|
|
3184
|
+
}
|
|
3185
|
+
const beforeZones = Object.keys(beforePhotos);
|
|
3186
|
+
const afterZones = Object.keys(afterPhotos);
|
|
3187
|
+
if (beforeZones.length !== afterZones.length) {
|
|
3188
|
+
return true;
|
|
3189
|
+
}
|
|
3190
|
+
for (const zoneId of afterZones) {
|
|
3191
|
+
const beforeZonePhotos = beforePhotos[zoneId];
|
|
3192
|
+
const afterZonePhotos = afterPhotos[zoneId];
|
|
3193
|
+
if (!beforeZonePhotos && !afterZonePhotos) {
|
|
3194
|
+
continue;
|
|
3195
|
+
}
|
|
3196
|
+
if (!beforeZonePhotos || !afterZonePhotos) {
|
|
3197
|
+
return true;
|
|
3198
|
+
}
|
|
3199
|
+
if (beforeZonePhotos.before !== afterZonePhotos.before || beforeZonePhotos.after !== afterZonePhotos.after || beforeZonePhotos.beforeNote !== afterZonePhotos.beforeNote || beforeZonePhotos.afterNote !== afterZonePhotos.afterNote) {
|
|
3200
|
+
return true;
|
|
3201
|
+
}
|
|
3202
|
+
}
|
|
3203
|
+
return false;
|
|
3204
|
+
}
|
|
3205
|
+
/**
|
|
3206
|
+
* Handles zone photos update notifications and logging
|
|
3207
|
+
* @param before - The appointment state before update
|
|
3208
|
+
* @param after - The appointment state after update
|
|
3209
|
+
*/
|
|
3210
|
+
async handleZonePhotosUpdate(before, after) {
|
|
3211
|
+
var _a, _b, _c;
|
|
3212
|
+
try {
|
|
3213
|
+
Logger.info(`[AggService] Processing zone photos update for appointment ${after.id}`);
|
|
3214
|
+
const beforePhotos = ((_a = before.metadata) == null ? void 0 : _a.zonePhotos) || {};
|
|
3215
|
+
const afterPhotos = ((_b = after.metadata) == null ? void 0 : _b.zonePhotos) || {};
|
|
3216
|
+
const updatedZones = [];
|
|
3217
|
+
const newPhotoTypes = [];
|
|
3218
|
+
for (const zoneId of Object.keys(afterPhotos)) {
|
|
3219
|
+
const beforeZonePhotos = beforePhotos[zoneId];
|
|
3220
|
+
const afterZonePhotos = afterPhotos[zoneId];
|
|
3221
|
+
if (!beforeZonePhotos) {
|
|
3222
|
+
updatedZones.push(zoneId);
|
|
3223
|
+
if (afterZonePhotos.before) {
|
|
3224
|
+
newPhotoTypes.push({ zoneId, photoType: "before" });
|
|
3225
|
+
}
|
|
3226
|
+
if (afterZonePhotos.after) {
|
|
3227
|
+
newPhotoTypes.push({ zoneId, photoType: "after" });
|
|
3228
|
+
}
|
|
3229
|
+
} else {
|
|
3230
|
+
if (beforeZonePhotos.before !== afterZonePhotos.before && afterZonePhotos.before) {
|
|
3231
|
+
updatedZones.push(zoneId);
|
|
3232
|
+
newPhotoTypes.push({ zoneId, photoType: "before" });
|
|
3233
|
+
}
|
|
3234
|
+
if (beforeZonePhotos.after !== afterZonePhotos.after && afterZonePhotos.after) {
|
|
3235
|
+
updatedZones.push(zoneId);
|
|
3236
|
+
newPhotoTypes.push({ zoneId, photoType: "after" });
|
|
3237
|
+
}
|
|
3238
|
+
}
|
|
3239
|
+
}
|
|
3240
|
+
if (updatedZones.length > 0) {
|
|
3241
|
+
Logger.info(
|
|
3242
|
+
`[AggService] Zone photos updated for appointment ${after.id}: ${updatedZones.join(
|
|
3243
|
+
", "
|
|
3244
|
+
)}`
|
|
3245
|
+
);
|
|
3246
|
+
for (const { zoneId, photoType } of newPhotoTypes) {
|
|
3247
|
+
Logger.info(
|
|
3248
|
+
`[AggService] New ${photoType} photo added for zone ${zoneId} in appointment ${after.id}`
|
|
3249
|
+
);
|
|
3250
|
+
}
|
|
3251
|
+
}
|
|
3252
|
+
const selectedZones = ((_c = after.metadata) == null ? void 0 : _c.selectedZones) || [];
|
|
3253
|
+
if (selectedZones.length > 0) {
|
|
3254
|
+
const completedZones = selectedZones.filter((zoneId) => {
|
|
3255
|
+
const zonePhotos = afterPhotos[zoneId];
|
|
3256
|
+
return zonePhotos && (zonePhotos.before || zonePhotos.after);
|
|
3257
|
+
});
|
|
3258
|
+
const completionPercentage = completedZones.length / selectedZones.length * 100;
|
|
3259
|
+
Logger.info(
|
|
3260
|
+
`[AggService] Photo completion for appointment ${after.id}: ${completionPercentage.toFixed(1)}% (${completedZones.length}/${selectedZones.length} zones)`
|
|
3261
|
+
);
|
|
3262
|
+
if (completionPercentage === 100) {
|
|
3263
|
+
Logger.info(`[AggService] All zone photos completed for appointment ${after.id}`);
|
|
3264
|
+
}
|
|
3265
|
+
}
|
|
3251
3266
|
} catch (error) {
|
|
3252
3267
|
Logger.error(
|
|
3253
|
-
`[AggService] Error
|
|
3268
|
+
`[AggService] Error handling zone photos update for appointment ${after.id}:`,
|
|
3254
3269
|
error
|
|
3255
3270
|
);
|
|
3256
|
-
return null;
|
|
3257
3271
|
}
|
|
3258
3272
|
}
|
|
3259
3273
|
};
|