@blackcode_sa/metaestetics-api 1.12.7 → 1.12.10
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 +51 -33
- package/dist/admin/index.d.ts +51 -33
- package/dist/admin/index.js +30 -9
- package/dist/admin/index.mjs +30 -9
- package/dist/index.d.mts +79 -65
- package/dist/index.d.ts +79 -65
- package/dist/index.js +301 -616
- package/dist/index.mjs +315 -631
- package/package.json +1 -1
- package/src/admin/aggregation/forms/README.md +13 -0
- package/src/admin/aggregation/forms/filled-forms.aggregation.service.ts +71 -51
- package/src/services/appointment/README.md +17 -0
- package/src/services/appointment/appointment.service.ts +233 -386
- package/src/services/auth/auth.service.ts +243 -466
- package/src/services/clinic/billing-transactions.service.ts +4 -1
- package/src/services/clinic/index.ts +5 -5
- package/src/types/clinic/preferences.types.ts +115 -97
package/dist/index.mjs
CHANGED
|
@@ -10,7 +10,8 @@ import {
|
|
|
10
10
|
query as query2,
|
|
11
11
|
limit as limit2,
|
|
12
12
|
startAfter as startAfter2,
|
|
13
|
-
getDocs as getDocs2
|
|
13
|
+
getDocs as getDocs2,
|
|
14
|
+
getCountFromServer
|
|
14
15
|
} from "firebase/firestore";
|
|
15
16
|
import { getFunctions } from "firebase/functions";
|
|
16
17
|
|
|
@@ -675,49 +676,67 @@ var Language = /* @__PURE__ */ ((Language2) => {
|
|
|
675
676
|
var ClinicTag = /* @__PURE__ */ ((ClinicTag6) => {
|
|
676
677
|
ClinicTag6["PARKING"] = "parking";
|
|
677
678
|
ClinicTag6["WIFI"] = "wifi";
|
|
678
|
-
ClinicTag6["
|
|
679
|
-
ClinicTag6["
|
|
680
|
-
ClinicTag6["
|
|
681
|
-
ClinicTag6["
|
|
679
|
+
ClinicTag6["LUXURY_WAITING"] = "luxury_waiting";
|
|
680
|
+
ClinicTag6["REFRESHMENTS"] = "refreshments";
|
|
681
|
+
ClinicTag6["PRIVATE_ROOMS"] = "private_rooms";
|
|
682
|
+
ClinicTag6["RECOVERY_AREA"] = "recovery_area";
|
|
682
683
|
ClinicTag6["CARD_PAYMENT"] = "card_payment";
|
|
683
|
-
ClinicTag6["
|
|
684
|
-
ClinicTag6["
|
|
685
|
-
ClinicTag6["
|
|
686
|
-
ClinicTag6["
|
|
687
|
-
ClinicTag6["
|
|
688
|
-
ClinicTag6["
|
|
689
|
-
ClinicTag6["
|
|
690
|
-
ClinicTag6["
|
|
691
|
-
ClinicTag6["
|
|
692
|
-
ClinicTag6["
|
|
693
|
-
ClinicTag6["
|
|
694
|
-
ClinicTag6["
|
|
695
|
-
ClinicTag6["
|
|
696
|
-
ClinicTag6["
|
|
697
|
-
ClinicTag6["
|
|
698
|
-
ClinicTag6["
|
|
699
|
-
ClinicTag6["
|
|
700
|
-
ClinicTag6["
|
|
701
|
-
ClinicTag6["
|
|
702
|
-
ClinicTag6["
|
|
703
|
-
ClinicTag6["
|
|
704
|
-
ClinicTag6["
|
|
705
|
-
ClinicTag6["
|
|
706
|
-
ClinicTag6["
|
|
684
|
+
ClinicTag6["FINANCING"] = "financing";
|
|
685
|
+
ClinicTag6["FREE_CONSULTATION"] = "free_consultation";
|
|
686
|
+
ClinicTag6["VIRTUAL_CONSULTATION"] = "virtual_consultation";
|
|
687
|
+
ClinicTag6["BEFORE_AFTER_PHOTOS"] = "before_after_photos";
|
|
688
|
+
ClinicTag6["AFTERCARE_SUPPORT"] = "aftercare_support";
|
|
689
|
+
ClinicTag6["BOTOX"] = "botox";
|
|
690
|
+
ClinicTag6["DERMAL_FILLERS"] = "dermal_fillers";
|
|
691
|
+
ClinicTag6["LASER_HAIR_REMOVAL"] = "laser_hair_removal";
|
|
692
|
+
ClinicTag6["LASER_SKIN_RESURFACING"] = "laser_skin_resurfacing";
|
|
693
|
+
ClinicTag6["CHEMICAL_PEELS"] = "chemical_peels";
|
|
694
|
+
ClinicTag6["MICRONEEDLING"] = "microneedling";
|
|
695
|
+
ClinicTag6["COOLSCULPTING"] = "coolsculpting";
|
|
696
|
+
ClinicTag6["THREAD_LIFT"] = "thread_lift";
|
|
697
|
+
ClinicTag6["LIP_ENHANCEMENT"] = "lip_enhancement";
|
|
698
|
+
ClinicTag6["RHINOPLASTY"] = "rhinoplasty";
|
|
699
|
+
ClinicTag6["SKIN_TIGHTENING"] = "skin_tightening";
|
|
700
|
+
ClinicTag6["FAT_DISSOLVING"] = "fat_dissolving";
|
|
701
|
+
ClinicTag6["PRP_TREATMENT"] = "prp_treatment";
|
|
702
|
+
ClinicTag6["HYDRAFACIAL"] = "hydrafacial";
|
|
703
|
+
ClinicTag6["IPL_PHOTOFACIAL"] = "ipl_photofacial";
|
|
704
|
+
ClinicTag6["BODY_CONTOURING"] = "body_contouring";
|
|
705
|
+
ClinicTag6["FACELIFT"] = "facelift";
|
|
706
|
+
ClinicTag6["RHINOPLASTY_SURGICAL"] = "rhinoplasty_surgical";
|
|
707
|
+
ClinicTag6["BREAST_AUGMENTATION"] = "breast_augmentation";
|
|
708
|
+
ClinicTag6["BREAST_REDUCTION"] = "breast_reduction";
|
|
709
|
+
ClinicTag6["BREAST_LIFT"] = "breast_lift";
|
|
710
|
+
ClinicTag6["TUMMY_TUCK"] = "tummy_tuck";
|
|
711
|
+
ClinicTag6["LIPOSUCTION"] = "liposuction";
|
|
712
|
+
ClinicTag6["BBL"] = "bbl";
|
|
713
|
+
ClinicTag6["MOMMY_MAKEOVER"] = "mommy_makeover";
|
|
714
|
+
ClinicTag6["ARM_LIFT"] = "arm_lift";
|
|
715
|
+
ClinicTag6["THIGH_LIFT"] = "thigh_lift";
|
|
716
|
+
ClinicTag6["EYELID_SURGERY"] = "eyelid_surgery";
|
|
717
|
+
ClinicTag6["BROW_LIFT"] = "brow_lift";
|
|
718
|
+
ClinicTag6["NECK_LIFT"] = "neck_lift";
|
|
719
|
+
ClinicTag6["OTOPLASTY"] = "otoplasty";
|
|
720
|
+
ClinicTag6["LABIAPLASTY"] = "labiaplasty";
|
|
707
721
|
ClinicTag6["ONLINE_BOOKING"] = "online_booking";
|
|
708
722
|
ClinicTag6["MOBILE_APP"] = "mobile_app";
|
|
709
723
|
ClinicTag6["SMS_NOTIFICATIONS"] = "sms_notifications";
|
|
710
724
|
ClinicTag6["EMAIL_NOTIFICATIONS"] = "email_notifications";
|
|
725
|
+
ClinicTag6["VIRTUAL_TRY_ON"] = "virtual_try_on";
|
|
726
|
+
ClinicTag6["SKIN_ANALYSIS"] = "skin_analysis";
|
|
727
|
+
ClinicTag6["TREATMENT_TRACKING"] = "treatment_tracking";
|
|
728
|
+
ClinicTag6["LOYALTY_PROGRAM"] = "loyalty_program";
|
|
711
729
|
ClinicTag6["ENGLISH"] = "english";
|
|
712
|
-
ClinicTag6["SERBIAN"] = "serbian";
|
|
713
730
|
ClinicTag6["GERMAN"] = "german";
|
|
714
|
-
ClinicTag6["RUSSIAN"] = "russian";
|
|
715
|
-
ClinicTag6["CHINESE"] = "chinese";
|
|
716
|
-
ClinicTag6["SPANISH"] = "spanish";
|
|
717
731
|
ClinicTag6["FRENCH"] = "french";
|
|
732
|
+
ClinicTag6["SPANISH"] = "spanish";
|
|
733
|
+
ClinicTag6["ITALIAN"] = "italian";
|
|
734
|
+
ClinicTag6["DUTCH"] = "dutch";
|
|
735
|
+
ClinicTag6["RUSSIAN"] = "russian";
|
|
736
|
+
ClinicTag6["PORTUGUESE"] = "portuguese";
|
|
718
737
|
ClinicTag6["OPEN_24_7"] = "open_24_7";
|
|
719
738
|
ClinicTag6["WEEKEND_HOURS"] = "weekend_hours";
|
|
720
|
-
ClinicTag6["
|
|
739
|
+
ClinicTag6["EXTENDED_HOURS"] = "extended_hours";
|
|
721
740
|
ClinicTag6["HOLIDAY_HOURS"] = "holiday_hours";
|
|
722
741
|
return ClinicTag6;
|
|
723
742
|
})(ClinicTag || {});
|
|
@@ -1053,24 +1072,18 @@ var AppointmentService = class extends BaseService {
|
|
|
1053
1072
|
`[APPOINTMENT_SERVICE] Getting available booking slots via HTTP for clinic: ${clinicId}, practitioner: ${practitionerId}, procedure: ${procedureId}`
|
|
1054
1073
|
);
|
|
1055
1074
|
if (!clinicId || !practitionerId || !procedureId || !startDate || !endDate) {
|
|
1056
|
-
throw new Error(
|
|
1057
|
-
"Missing required parameters for booking slots calculation"
|
|
1058
|
-
);
|
|
1075
|
+
throw new Error("Missing required parameters for booking slots calculation");
|
|
1059
1076
|
}
|
|
1060
1077
|
if (endDate <= startDate) {
|
|
1061
1078
|
throw new Error("End date must be after start date");
|
|
1062
1079
|
}
|
|
1063
1080
|
const currentUser = this.auth.currentUser;
|
|
1064
1081
|
if (!currentUser) {
|
|
1065
|
-
throw new Error(
|
|
1066
|
-
"User must be authenticated to get available booking slots"
|
|
1067
|
-
);
|
|
1082
|
+
throw new Error("User must be authenticated to get available booking slots");
|
|
1068
1083
|
}
|
|
1069
1084
|
const functionUrl = `https://europe-west6-metaestetics.cloudfunctions.net/bookingApi/getAvailableBookingSlots`;
|
|
1070
1085
|
const idToken = await currentUser.getIdToken();
|
|
1071
|
-
console.log(
|
|
1072
|
-
`[APPOINTMENT_SERVICE] Got user token, user ID: ${currentUser.uid}`
|
|
1073
|
-
);
|
|
1086
|
+
console.log(`[APPOINTMENT_SERVICE] Got user token, user ID: ${currentUser.uid}`);
|
|
1074
1087
|
const requestData = {
|
|
1075
1088
|
clinicId,
|
|
1076
1089
|
practitionerId,
|
|
@@ -1081,9 +1094,7 @@ var AppointmentService = class extends BaseService {
|
|
|
1081
1094
|
end: endDate.getTime()
|
|
1082
1095
|
}
|
|
1083
1096
|
};
|
|
1084
|
-
console.log(
|
|
1085
|
-
`[APPOINTMENT_SERVICE] Making fetch request to ${functionUrl}`
|
|
1086
|
-
);
|
|
1097
|
+
console.log(`[APPOINTMENT_SERVICE] Making fetch request to ${functionUrl}`);
|
|
1087
1098
|
const response = await fetch(functionUrl, {
|
|
1088
1099
|
method: "POST",
|
|
1089
1100
|
mode: "cors",
|
|
@@ -1105,9 +1116,7 @@ var AppointmentService = class extends BaseService {
|
|
|
1105
1116
|
);
|
|
1106
1117
|
if (!response.ok) {
|
|
1107
1118
|
const errorText = await response.text();
|
|
1108
|
-
console.error(
|
|
1109
|
-
`[APPOINTMENT_SERVICE] Error response details: ${errorText}`
|
|
1110
|
-
);
|
|
1119
|
+
console.error(`[APPOINTMENT_SERVICE] Error response details: ${errorText}`);
|
|
1111
1120
|
throw new Error(
|
|
1112
1121
|
`Failed to get available booking slots: ${response.status} ${response.statusText} - ${errorText}`
|
|
1113
1122
|
);
|
|
@@ -1115,24 +1124,15 @@ var AppointmentService = class extends BaseService {
|
|
|
1115
1124
|
const result = await response.json();
|
|
1116
1125
|
console.log(`[APPOINTMENT_SERVICE] Response parsed successfully`, result);
|
|
1117
1126
|
if (!result.success) {
|
|
1118
|
-
throw new Error(
|
|
1119
|
-
result.error || "Failed to get available booking slots"
|
|
1120
|
-
);
|
|
1127
|
+
throw new Error(result.error || "Failed to get available booking slots");
|
|
1121
1128
|
}
|
|
1122
|
-
const slots = result.availableSlots.map(
|
|
1123
|
-
(slot)
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
);
|
|
1127
|
-
console.log(
|
|
1128
|
-
`[APPOINTMENT_SERVICE] Found ${slots.length} available booking slots via HTTP`
|
|
1129
|
-
);
|
|
1129
|
+
const slots = result.availableSlots.map((slot) => ({
|
|
1130
|
+
start: new Date(slot.start)
|
|
1131
|
+
}));
|
|
1132
|
+
console.log(`[APPOINTMENT_SERVICE] Found ${slots.length} available booking slots via HTTP`);
|
|
1130
1133
|
return slots;
|
|
1131
1134
|
} catch (error) {
|
|
1132
|
-
console.error(
|
|
1133
|
-
"[APPOINTMENT_SERVICE] Error getting available booking slots via HTTP:",
|
|
1134
|
-
error
|
|
1135
|
-
);
|
|
1135
|
+
console.error("[APPOINTMENT_SERVICE] Error getting available booking slots via HTTP:", error);
|
|
1136
1136
|
throw error;
|
|
1137
1137
|
}
|
|
1138
1138
|
}
|
|
@@ -1144,9 +1144,7 @@ var AppointmentService = class extends BaseService {
|
|
|
1144
1144
|
*/
|
|
1145
1145
|
async createAppointmentHttp(data) {
|
|
1146
1146
|
try {
|
|
1147
|
-
console.log(
|
|
1148
|
-
"[APPOINTMENT_SERVICE] Creating appointment via cloud function"
|
|
1149
|
-
);
|
|
1147
|
+
console.log("[APPOINTMENT_SERVICE] Creating appointment via cloud function");
|
|
1150
1148
|
const currentUser = this.auth.currentUser;
|
|
1151
1149
|
if (!currentUser) {
|
|
1152
1150
|
throw new Error("User must be authenticated to create an appointment");
|
|
@@ -1160,9 +1158,7 @@ var AppointmentService = class extends BaseService {
|
|
|
1160
1158
|
appointmentEndTime: data.appointmentEndTime.toMillis ? data.appointmentEndTime.toMillis() : new Date(data.appointmentEndTime).getTime(),
|
|
1161
1159
|
patientNotes: (data == null ? void 0 : data.patientNotes) || null
|
|
1162
1160
|
};
|
|
1163
|
-
console.log(
|
|
1164
|
-
`[APPOINTMENT_SERVICE] Making fetch request to ${functionUrl}`
|
|
1165
|
-
);
|
|
1161
|
+
console.log(`[APPOINTMENT_SERVICE] Making fetch request to ${functionUrl}`);
|
|
1166
1162
|
const response = await fetch(functionUrl, {
|
|
1167
1163
|
method: "POST",
|
|
1168
1164
|
mode: "cors",
|
|
@@ -1181,9 +1177,7 @@ var AppointmentService = class extends BaseService {
|
|
|
1181
1177
|
);
|
|
1182
1178
|
if (!response.ok) {
|
|
1183
1179
|
const errorText = await response.text();
|
|
1184
|
-
console.error(
|
|
1185
|
-
`[APPOINTMENT_SERVICE] Error response details: ${errorText}`
|
|
1186
|
-
);
|
|
1180
|
+
console.error(`[APPOINTMENT_SERVICE] Error response details: ${errorText}`);
|
|
1187
1181
|
throw new Error(
|
|
1188
1182
|
`Failed to create appointment: ${response.status} ${response.statusText} - ${errorText}`
|
|
1189
1183
|
);
|
|
@@ -1193,25 +1187,16 @@ var AppointmentService = class extends BaseService {
|
|
|
1193
1187
|
throw new Error(result.error || "Failed to create appointment");
|
|
1194
1188
|
}
|
|
1195
1189
|
if (result.appointmentData) {
|
|
1196
|
-
console.log(
|
|
1197
|
-
`[APPOINTMENT_SERVICE] Appointment created with ID: ${result.appointmentId}`
|
|
1198
|
-
);
|
|
1190
|
+
console.log(`[APPOINTMENT_SERVICE] Appointment created with ID: ${result.appointmentId}`);
|
|
1199
1191
|
return result.appointmentData;
|
|
1200
1192
|
}
|
|
1201
|
-
const createdAppointment = await this.getAppointmentById(
|
|
1202
|
-
result.appointmentId
|
|
1203
|
-
);
|
|
1193
|
+
const createdAppointment = await this.getAppointmentById(result.appointmentId);
|
|
1204
1194
|
if (!createdAppointment) {
|
|
1205
|
-
throw new Error(
|
|
1206
|
-
`Failed to retrieve created appointment with ID: ${result.appointmentId}`
|
|
1207
|
-
);
|
|
1195
|
+
throw new Error(`Failed to retrieve created appointment with ID: ${result.appointmentId}`);
|
|
1208
1196
|
}
|
|
1209
1197
|
return createdAppointment;
|
|
1210
1198
|
} catch (error) {
|
|
1211
|
-
console.error(
|
|
1212
|
-
"[APPOINTMENT_SERVICE] Error creating appointment via cloud function:",
|
|
1213
|
-
error
|
|
1214
|
-
);
|
|
1199
|
+
console.error("[APPOINTMENT_SERVICE] Error creating appointment via cloud function:", error);
|
|
1215
1200
|
throw error;
|
|
1216
1201
|
}
|
|
1217
1202
|
}
|
|
@@ -1223,19 +1208,14 @@ var AppointmentService = class extends BaseService {
|
|
|
1223
1208
|
*/
|
|
1224
1209
|
async getAppointmentById(appointmentId) {
|
|
1225
1210
|
try {
|
|
1226
|
-
console.log(
|
|
1227
|
-
`[APPOINTMENT_SERVICE] Getting appointment with ID: ${appointmentId}`
|
|
1228
|
-
);
|
|
1211
|
+
console.log(`[APPOINTMENT_SERVICE] Getting appointment with ID: ${appointmentId}`);
|
|
1229
1212
|
const appointment = await getAppointmentByIdUtil(this.db, appointmentId);
|
|
1230
1213
|
console.log(
|
|
1231
1214
|
`[APPOINTMENT_SERVICE] Appointment ${appointmentId} ${appointment ? "found" : "not found"}`
|
|
1232
1215
|
);
|
|
1233
1216
|
return appointment;
|
|
1234
1217
|
} catch (error) {
|
|
1235
|
-
console.error(
|
|
1236
|
-
`[APPOINTMENT_SERVICE] Error getting appointment ${appointmentId}:`,
|
|
1237
|
-
error
|
|
1238
|
-
);
|
|
1218
|
+
console.error(`[APPOINTMENT_SERVICE] Error getting appointment ${appointmentId}:`, error);
|
|
1239
1219
|
throw error;
|
|
1240
1220
|
}
|
|
1241
1221
|
}
|
|
@@ -1248,24 +1228,13 @@ var AppointmentService = class extends BaseService {
|
|
|
1248
1228
|
*/
|
|
1249
1229
|
async updateAppointment(appointmentId, data) {
|
|
1250
1230
|
try {
|
|
1251
|
-
console.log(
|
|
1252
|
-
`[APPOINTMENT_SERVICE] Updating appointment with ID: ${appointmentId}`
|
|
1253
|
-
);
|
|
1231
|
+
console.log(`[APPOINTMENT_SERVICE] Updating appointment with ID: ${appointmentId}`);
|
|
1254
1232
|
const validatedData = await updateAppointmentSchema.parseAsync(data);
|
|
1255
|
-
const updatedAppointment = await updateAppointmentUtil(
|
|
1256
|
-
|
|
1257
|
-
appointmentId,
|
|
1258
|
-
validatedData
|
|
1259
|
-
);
|
|
1260
|
-
console.log(
|
|
1261
|
-
`[APPOINTMENT_SERVICE] Appointment ${appointmentId} updated successfully`
|
|
1262
|
-
);
|
|
1233
|
+
const updatedAppointment = await updateAppointmentUtil(this.db, appointmentId, validatedData);
|
|
1234
|
+
console.log(`[APPOINTMENT_SERVICE] Appointment ${appointmentId} updated successfully`);
|
|
1263
1235
|
return updatedAppointment;
|
|
1264
1236
|
} catch (error) {
|
|
1265
|
-
console.error(
|
|
1266
|
-
`[APPOINTMENT_SERVICE] Error updating appointment ${appointmentId}:`,
|
|
1267
|
-
error
|
|
1268
|
-
);
|
|
1237
|
+
console.error(`[APPOINTMENT_SERVICE] Error updating appointment ${appointmentId}:`, error);
|
|
1269
1238
|
throw error;
|
|
1270
1239
|
}
|
|
1271
1240
|
}
|
|
@@ -1277,21 +1246,13 @@ var AppointmentService = class extends BaseService {
|
|
|
1277
1246
|
*/
|
|
1278
1247
|
async searchAppointments(params) {
|
|
1279
1248
|
try {
|
|
1280
|
-
console.log(
|
|
1281
|
-
"[APPOINTMENT_SERVICE] Searching appointments with params:",
|
|
1282
|
-
params
|
|
1283
|
-
);
|
|
1249
|
+
console.log("[APPOINTMENT_SERVICE] Searching appointments with params:", params);
|
|
1284
1250
|
await searchAppointmentsSchema.parseAsync(params);
|
|
1285
1251
|
const result = await searchAppointmentsUtil(this.db, params);
|
|
1286
|
-
console.log(
|
|
1287
|
-
`[APPOINTMENT_SERVICE] Found ${result.appointments.length} appointments`
|
|
1288
|
-
);
|
|
1252
|
+
console.log(`[APPOINTMENT_SERVICE] Found ${result.appointments.length} appointments`);
|
|
1289
1253
|
return result;
|
|
1290
1254
|
} catch (error) {
|
|
1291
|
-
console.error(
|
|
1292
|
-
"[APPOINTMENT_SERVICE] Error searching appointments:",
|
|
1293
|
-
error
|
|
1294
|
-
);
|
|
1255
|
+
console.error("[APPOINTMENT_SERVICE] Error searching appointments:", error);
|
|
1295
1256
|
throw error;
|
|
1296
1257
|
}
|
|
1297
1258
|
}
|
|
@@ -1303,9 +1264,7 @@ var AppointmentService = class extends BaseService {
|
|
|
1303
1264
|
* @returns Found appointments and the last document for pagination
|
|
1304
1265
|
*/
|
|
1305
1266
|
async getPatientAppointments(patientId, options) {
|
|
1306
|
-
console.log(
|
|
1307
|
-
`[APPOINTMENT_SERVICE] Getting appointments for patient: ${patientId}`
|
|
1308
|
-
);
|
|
1267
|
+
console.log(`[APPOINTMENT_SERVICE] Getting appointments for patient: ${patientId}`);
|
|
1309
1268
|
const searchParams = {
|
|
1310
1269
|
patientId,
|
|
1311
1270
|
startDate: options == null ? void 0 : options.startDate,
|
|
@@ -1324,9 +1283,7 @@ var AppointmentService = class extends BaseService {
|
|
|
1324
1283
|
* @returns Found appointments and the last document for pagination
|
|
1325
1284
|
*/
|
|
1326
1285
|
async getPractitionerAppointments(practitionerId, options) {
|
|
1327
|
-
console.log(
|
|
1328
|
-
`[APPOINTMENT_SERVICE] Getting appointments for practitioner: ${practitionerId}`
|
|
1329
|
-
);
|
|
1286
|
+
console.log(`[APPOINTMENT_SERVICE] Getting appointments for practitioner: ${practitionerId}`);
|
|
1330
1287
|
const searchParams = {
|
|
1331
1288
|
practitionerId,
|
|
1332
1289
|
startDate: options == null ? void 0 : options.startDate,
|
|
@@ -1345,9 +1302,7 @@ var AppointmentService = class extends BaseService {
|
|
|
1345
1302
|
* @returns Found appointments and the last document for pagination
|
|
1346
1303
|
*/
|
|
1347
1304
|
async getClinicAppointments(clinicBranchId, options) {
|
|
1348
|
-
console.log(
|
|
1349
|
-
`[APPOINTMENT_SERVICE] Getting appointments for clinic: ${clinicBranchId}`
|
|
1350
|
-
);
|
|
1305
|
+
console.log(`[APPOINTMENT_SERVICE] Getting appointments for clinic: ${clinicBranchId}`);
|
|
1351
1306
|
const searchParams = {
|
|
1352
1307
|
clinicBranchId,
|
|
1353
1308
|
practitionerId: options == null ? void 0 : options.practitionerId,
|
|
@@ -1398,68 +1353,42 @@ var AppointmentService = class extends BaseService {
|
|
|
1398
1353
|
* Confirms a PENDING appointment by an Admin/Clinic.
|
|
1399
1354
|
*/
|
|
1400
1355
|
async confirmAppointmentAdmin(appointmentId) {
|
|
1401
|
-
console.log(
|
|
1402
|
-
`[APPOINTMENT_SERVICE] Admin confirming appointment: ${appointmentId}`
|
|
1403
|
-
);
|
|
1356
|
+
console.log(`[APPOINTMENT_SERVICE] Admin confirming appointment: ${appointmentId}`);
|
|
1404
1357
|
const appointment = await this.getAppointmentById(appointmentId);
|
|
1405
|
-
if (!appointment)
|
|
1406
|
-
throw new Error(`Appointment ${appointmentId} not found.`);
|
|
1358
|
+
if (!appointment) throw new Error(`Appointment ${appointmentId} not found.`);
|
|
1407
1359
|
if (appointment.status !== "pending" /* PENDING */) {
|
|
1408
|
-
throw new Error(
|
|
1409
|
-
`Appointment ${appointmentId} is not in PENDING state to be confirmed.`
|
|
1410
|
-
);
|
|
1360
|
+
throw new Error(`Appointment ${appointmentId} is not in PENDING state to be confirmed.`);
|
|
1411
1361
|
}
|
|
1412
|
-
return this.updateAppointmentStatus(
|
|
1413
|
-
appointmentId,
|
|
1414
|
-
"confirmed" /* CONFIRMED */
|
|
1415
|
-
);
|
|
1362
|
+
return this.updateAppointmentStatus(appointmentId, "confirmed" /* CONFIRMED */);
|
|
1416
1363
|
}
|
|
1417
1364
|
/**
|
|
1418
1365
|
* Cancels an appointment by the User (Patient).
|
|
1419
1366
|
*/
|
|
1420
1367
|
async cancelAppointmentUser(appointmentId, reason) {
|
|
1421
|
-
console.log(
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
"canceled_patient" /* CANCELED_PATIENT */,
|
|
1427
|
-
{
|
|
1428
|
-
cancellationReason: reason,
|
|
1429
|
-
canceledBy: "patient"
|
|
1430
|
-
}
|
|
1431
|
-
);
|
|
1368
|
+
console.log(`[APPOINTMENT_SERVICE] User canceling appointment: ${appointmentId}`);
|
|
1369
|
+
return this.updateAppointmentStatus(appointmentId, "canceled_patient" /* CANCELED_PATIENT */, {
|
|
1370
|
+
cancellationReason: reason,
|
|
1371
|
+
canceledBy: "patient"
|
|
1372
|
+
});
|
|
1432
1373
|
}
|
|
1433
1374
|
/**
|
|
1434
1375
|
* Cancels an appointment by an Admin/Clinic.
|
|
1435
1376
|
*/
|
|
1436
1377
|
async cancelAppointmentAdmin(appointmentId, reason) {
|
|
1437
|
-
console.log(
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
"canceled_clinic" /* CANCELED_CLINIC */,
|
|
1443
|
-
{
|
|
1444
|
-
cancellationReason: reason,
|
|
1445
|
-
canceledBy: "clinic"
|
|
1446
|
-
}
|
|
1447
|
-
);
|
|
1378
|
+
console.log(`[APPOINTMENT_SERVICE] Admin canceling appointment: ${appointmentId}`);
|
|
1379
|
+
return this.updateAppointmentStatus(appointmentId, "canceled_clinic" /* CANCELED_CLINIC */, {
|
|
1380
|
+
cancellationReason: reason,
|
|
1381
|
+
canceledBy: "clinic"
|
|
1382
|
+
});
|
|
1448
1383
|
}
|
|
1449
1384
|
/**
|
|
1450
1385
|
* Admin proposes to reschedule an appointment.
|
|
1451
1386
|
* Sets status to RESCHEDULED_BY_CLINIC and updates times.
|
|
1452
1387
|
*/
|
|
1453
1388
|
async rescheduleAppointmentAdmin(params) {
|
|
1454
|
-
console.log(
|
|
1455
|
-
|
|
1456
|
-
);
|
|
1457
|
-
const validatedParams = await rescheduleAppointmentSchema.parseAsync(
|
|
1458
|
-
params
|
|
1459
|
-
);
|
|
1460
|
-
const startTimestamp = this.convertToTimestamp(
|
|
1461
|
-
validatedParams.newStartTime
|
|
1462
|
-
);
|
|
1389
|
+
console.log(`[APPOINTMENT_SERVICE] Admin rescheduling appointment: ${params.appointmentId}`);
|
|
1390
|
+
const validatedParams = await rescheduleAppointmentSchema.parseAsync(params);
|
|
1391
|
+
const startTimestamp = this.convertToTimestamp(validatedParams.newStartTime);
|
|
1463
1392
|
const endTimestamp = this.convertToTimestamp(validatedParams.newEndTime);
|
|
1464
1393
|
if (endTimestamp.toMillis() <= startTimestamp.toMillis()) {
|
|
1465
1394
|
throw new Error("New end time must be after new start time.");
|
|
@@ -1502,48 +1431,31 @@ var AppointmentService = class extends BaseService {
|
|
|
1502
1431
|
if (value && typeof value.seconds === "number") {
|
|
1503
1432
|
return new Timestamp2(value.seconds, value.nanoseconds || 0);
|
|
1504
1433
|
}
|
|
1505
|
-
throw new Error(
|
|
1506
|
-
`Invalid timestamp format: ${typeof value}, value: ${JSON.stringify(
|
|
1507
|
-
value
|
|
1508
|
-
)}`
|
|
1509
|
-
);
|
|
1434
|
+
throw new Error(`Invalid timestamp format: ${typeof value}, value: ${JSON.stringify(value)}`);
|
|
1510
1435
|
}
|
|
1511
1436
|
/**
|
|
1512
1437
|
* User confirms a reschedule proposed by the clinic.
|
|
1513
1438
|
* Status changes from RESCHEDULED_BY_CLINIC to CONFIRMED.
|
|
1514
1439
|
*/
|
|
1515
1440
|
async rescheduleAppointmentConfirmUser(appointmentId) {
|
|
1516
|
-
console.log(
|
|
1517
|
-
`[APPOINTMENT_SERVICE] User confirming reschedule for: ${appointmentId}`
|
|
1518
|
-
);
|
|
1441
|
+
console.log(`[APPOINTMENT_SERVICE] User confirming reschedule for: ${appointmentId}`);
|
|
1519
1442
|
const appointment = await this.getAppointmentById(appointmentId);
|
|
1520
|
-
if (!appointment)
|
|
1521
|
-
throw new Error(`Appointment ${appointmentId} not found.`);
|
|
1443
|
+
if (!appointment) throw new Error(`Appointment ${appointmentId} not found.`);
|
|
1522
1444
|
if (appointment.status !== "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */) {
|
|
1523
|
-
throw new Error(
|
|
1524
|
-
`Appointment ${appointmentId} is not in RESCHEDULED_BY_CLINIC state.`
|
|
1525
|
-
);
|
|
1445
|
+
throw new Error(`Appointment ${appointmentId} is not in RESCHEDULED_BY_CLINIC state.`);
|
|
1526
1446
|
}
|
|
1527
|
-
return this.updateAppointmentStatus(
|
|
1528
|
-
appointmentId,
|
|
1529
|
-
"confirmed" /* CONFIRMED */
|
|
1530
|
-
);
|
|
1447
|
+
return this.updateAppointmentStatus(appointmentId, "confirmed" /* CONFIRMED */);
|
|
1531
1448
|
}
|
|
1532
1449
|
/**
|
|
1533
1450
|
* User rejects a reschedule proposed by the clinic.
|
|
1534
1451
|
* Status changes from RESCHEDULED_BY_CLINIC to CANCELED_PATIENT_RESCHEDULED.
|
|
1535
1452
|
*/
|
|
1536
1453
|
async rescheduleAppointmentRejectUser(appointmentId, reason) {
|
|
1537
|
-
console.log(
|
|
1538
|
-
`[APPOINTMENT_SERVICE] User rejecting reschedule for: ${appointmentId}`
|
|
1539
|
-
);
|
|
1454
|
+
console.log(`[APPOINTMENT_SERVICE] User rejecting reschedule for: ${appointmentId}`);
|
|
1540
1455
|
const appointment = await this.getAppointmentById(appointmentId);
|
|
1541
|
-
if (!appointment)
|
|
1542
|
-
throw new Error(`Appointment ${appointmentId} not found.`);
|
|
1456
|
+
if (!appointment) throw new Error(`Appointment ${appointmentId} not found.`);
|
|
1543
1457
|
if (appointment.status !== "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */) {
|
|
1544
|
-
throw new Error(
|
|
1545
|
-
`Appointment ${appointmentId} is not in RESCHEDULED_BY_CLINIC state.`
|
|
1546
|
-
);
|
|
1458
|
+
throw new Error(`Appointment ${appointmentId} is not in RESCHEDULED_BY_CLINIC state.`);
|
|
1547
1459
|
}
|
|
1548
1460
|
return this.updateAppointmentStatus(
|
|
1549
1461
|
appointmentId,
|
|
@@ -1559,17 +1471,12 @@ var AppointmentService = class extends BaseService {
|
|
|
1559
1471
|
* Requires all pending user forms to be completed.
|
|
1560
1472
|
*/
|
|
1561
1473
|
async checkInPatientAdmin(appointmentId) {
|
|
1562
|
-
console.log(
|
|
1563
|
-
`[APPOINTMENT_SERVICE] Admin checking in patient for: ${appointmentId}`
|
|
1564
|
-
);
|
|
1474
|
+
console.log(`[APPOINTMENT_SERVICE] Admin checking in patient for: ${appointmentId}`);
|
|
1565
1475
|
const appointment = await this.getAppointmentById(appointmentId);
|
|
1566
|
-
if (!appointment)
|
|
1567
|
-
throw new Error(`Appointment ${appointmentId} not found.`);
|
|
1476
|
+
if (!appointment) throw new Error(`Appointment ${appointmentId} not found.`);
|
|
1568
1477
|
if (appointment.pendingUserFormsIds && appointment.pendingUserFormsIds.length > 0) {
|
|
1569
1478
|
throw new Error(
|
|
1570
|
-
`Cannot check in: Patient has ${appointment.pendingUserFormsIds.length} pending required form(s). IDs: ${appointment.pendingUserFormsIds.join(
|
|
1571
|
-
", "
|
|
1572
|
-
)}`
|
|
1479
|
+
`Cannot check in: Patient has ${appointment.pendingUserFormsIds.length} pending required form(s). IDs: ${appointment.pendingUserFormsIds.join(", ")}`
|
|
1573
1480
|
);
|
|
1574
1481
|
}
|
|
1575
1482
|
if (appointment.status !== "confirmed" /* CONFIRMED */ && appointment.status !== "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */) {
|
|
@@ -1577,25 +1484,17 @@ var AppointmentService = class extends BaseService {
|
|
|
1577
1484
|
`Checking in appointment ${appointmentId} with status ${appointment.status}. Ensure this is intended.`
|
|
1578
1485
|
);
|
|
1579
1486
|
}
|
|
1580
|
-
return this.updateAppointmentStatus(
|
|
1581
|
-
appointmentId,
|
|
1582
|
-
"checked_in" /* CHECKED_IN */
|
|
1583
|
-
);
|
|
1487
|
+
return this.updateAppointmentStatus(appointmentId, "checked_in" /* CHECKED_IN */);
|
|
1584
1488
|
}
|
|
1585
1489
|
/**
|
|
1586
1490
|
* Doctor starts the appointment procedure.
|
|
1587
1491
|
*/
|
|
1588
1492
|
async startAppointmentDoctor(appointmentId) {
|
|
1589
|
-
console.log(
|
|
1590
|
-
`[APPOINTMENT_SERVICE] Doctor starting appointment: ${appointmentId}`
|
|
1591
|
-
);
|
|
1493
|
+
console.log(`[APPOINTMENT_SERVICE] Doctor starting appointment: ${appointmentId}`);
|
|
1592
1494
|
const appointment = await this.getAppointmentById(appointmentId);
|
|
1593
|
-
if (!appointment)
|
|
1594
|
-
throw new Error(`Appointment ${appointmentId} not found.`);
|
|
1495
|
+
if (!appointment) throw new Error(`Appointment ${appointmentId} not found.`);
|
|
1595
1496
|
if (appointment.status !== "checked_in" /* CHECKED_IN */) {
|
|
1596
|
-
throw new Error(
|
|
1597
|
-
`Appointment ${appointmentId} must be CHECKED_IN to start.`
|
|
1598
|
-
);
|
|
1497
|
+
throw new Error(`Appointment ${appointmentId} must be CHECKED_IN to start.`);
|
|
1599
1498
|
}
|
|
1600
1499
|
const updateData = {
|
|
1601
1500
|
status: "in_progress" /* IN_PROGRESS */,
|
|
@@ -1609,24 +1508,18 @@ var AppointmentService = class extends BaseService {
|
|
|
1609
1508
|
* Doctor completes and finalizes the appointment.
|
|
1610
1509
|
*/
|
|
1611
1510
|
async completeAppointmentDoctor(appointmentId, finalizationNotes, actualDurationMinutesInput) {
|
|
1612
|
-
console.log(
|
|
1613
|
-
`[APPOINTMENT_SERVICE] Doctor completing appointment: ${appointmentId}`
|
|
1614
|
-
);
|
|
1511
|
+
console.log(`[APPOINTMENT_SERVICE] Doctor completing appointment: ${appointmentId}`);
|
|
1615
1512
|
const currentUser = this.auth.currentUser;
|
|
1616
|
-
if (!currentUser)
|
|
1617
|
-
throw new Error("Authentication required to complete appointment.");
|
|
1513
|
+
if (!currentUser) throw new Error("Authentication required to complete appointment.");
|
|
1618
1514
|
const appointment = await this.getAppointmentById(appointmentId);
|
|
1619
|
-
if (!appointment)
|
|
1620
|
-
throw new Error(`Appointment ${appointmentId} not found.`);
|
|
1515
|
+
if (!appointment) throw new Error(`Appointment ${appointmentId} not found.`);
|
|
1621
1516
|
let calculatedDurationMinutes = actualDurationMinutesInput;
|
|
1622
1517
|
const procedureCompletionTime = Timestamp2.now();
|
|
1623
1518
|
if (calculatedDurationMinutes === void 0 && appointment.procedureActualStartTime) {
|
|
1624
1519
|
const startTimeMillis = appointment.procedureActualStartTime.toMillis();
|
|
1625
1520
|
const endTimeMillis = procedureCompletionTime.toMillis();
|
|
1626
1521
|
if (endTimeMillis > startTimeMillis) {
|
|
1627
|
-
calculatedDurationMinutes = Math.round(
|
|
1628
|
-
(endTimeMillis - startTimeMillis) / 6e4
|
|
1629
|
-
);
|
|
1522
|
+
calculatedDurationMinutes = Math.round((endTimeMillis - startTimeMillis) / 6e4);
|
|
1630
1523
|
}
|
|
1631
1524
|
}
|
|
1632
1525
|
const updateData = {
|
|
@@ -1650,31 +1543,22 @@ var AppointmentService = class extends BaseService {
|
|
|
1650
1543
|
* Admin marks an appointment as No-Show.
|
|
1651
1544
|
*/
|
|
1652
1545
|
async markNoShowAdmin(appointmentId) {
|
|
1653
|
-
console.log(
|
|
1654
|
-
`[APPOINTMENT_SERVICE] Admin marking no-show for: ${appointmentId}`
|
|
1655
|
-
);
|
|
1546
|
+
console.log(`[APPOINTMENT_SERVICE] Admin marking no-show for: ${appointmentId}`);
|
|
1656
1547
|
const appointment = await this.getAppointmentById(appointmentId);
|
|
1657
|
-
if (!appointment)
|
|
1658
|
-
throw new Error(`Appointment ${appointmentId} not found.`);
|
|
1548
|
+
if (!appointment) throw new Error(`Appointment ${appointmentId} not found.`);
|
|
1659
1549
|
if (Timestamp2.now().toMillis() < appointment.appointmentStartTime.toMillis()) {
|
|
1660
1550
|
throw new Error("Cannot mark no-show before appointment start time.");
|
|
1661
1551
|
}
|
|
1662
|
-
return this.updateAppointmentStatus(
|
|
1663
|
-
|
|
1664
|
-
"
|
|
1665
|
-
|
|
1666
|
-
cancellationReason: "Patient did not show up for the appointment.",
|
|
1667
|
-
canceledBy: "clinic"
|
|
1668
|
-
}
|
|
1669
|
-
);
|
|
1552
|
+
return this.updateAppointmentStatus(appointmentId, "no_show" /* NO_SHOW */, {
|
|
1553
|
+
cancellationReason: "Patient did not show up for the appointment.",
|
|
1554
|
+
canceledBy: "clinic"
|
|
1555
|
+
});
|
|
1670
1556
|
}
|
|
1671
1557
|
/**
|
|
1672
1558
|
* Adds a media item to an appointment.
|
|
1673
1559
|
*/
|
|
1674
1560
|
async addMediaToAppointment(appointmentId, mediaItemData) {
|
|
1675
|
-
console.log(
|
|
1676
|
-
`[APPOINTMENT_SERVICE] Adding media to appointment ${appointmentId}`
|
|
1677
|
-
);
|
|
1561
|
+
console.log(`[APPOINTMENT_SERVICE] Adding media to appointment ${appointmentId}`);
|
|
1678
1562
|
const currentUser = this.auth.currentUser;
|
|
1679
1563
|
if (!currentUser) throw new Error("Authentication required.");
|
|
1680
1564
|
const newMediaItem = {
|
|
@@ -1714,9 +1598,7 @@ var AppointmentService = class extends BaseService {
|
|
|
1714
1598
|
* Adds or updates review information for an appointment.
|
|
1715
1599
|
*/
|
|
1716
1600
|
async addReviewToAppointment(appointmentId, reviewData) {
|
|
1717
|
-
console.log(
|
|
1718
|
-
`[APPOINTMENT_SERVICE] Adding review to appointment ${appointmentId}`
|
|
1719
|
-
);
|
|
1601
|
+
console.log(`[APPOINTMENT_SERVICE] Adding review to appointment ${appointmentId}`);
|
|
1720
1602
|
const newReviewInfo = {
|
|
1721
1603
|
...reviewData,
|
|
1722
1604
|
reviewId: this.generateId(),
|
|
@@ -1750,9 +1632,7 @@ var AppointmentService = class extends BaseService {
|
|
|
1750
1632
|
* @returns The updated appointment
|
|
1751
1633
|
*/
|
|
1752
1634
|
async updateInternalNotes(appointmentId, notes) {
|
|
1753
|
-
console.log(
|
|
1754
|
-
`[APPOINTMENT_SERVICE] Updating internal notes for appointment: ${appointmentId}`
|
|
1755
|
-
);
|
|
1635
|
+
console.log(`[APPOINTMENT_SERVICE] Updating internal notes for appointment: ${appointmentId}`);
|
|
1756
1636
|
const updateData = {
|
|
1757
1637
|
internalNotes: notes
|
|
1758
1638
|
};
|
|
@@ -1768,9 +1648,7 @@ var AppointmentService = class extends BaseService {
|
|
|
1768
1648
|
*/
|
|
1769
1649
|
async getUpcomingPatientAppointments(patientId, options) {
|
|
1770
1650
|
try {
|
|
1771
|
-
console.log(
|
|
1772
|
-
`[APPOINTMENT_SERVICE] Getting upcoming appointments for patient: ${patientId}`
|
|
1773
|
-
);
|
|
1651
|
+
console.log(`[APPOINTMENT_SERVICE] Getting upcoming appointments for patient: ${patientId}`);
|
|
1774
1652
|
const effectiveStartDate = (options == null ? void 0 : options.startDate) || /* @__PURE__ */ new Date();
|
|
1775
1653
|
const upcomingStatuses = [
|
|
1776
1654
|
"pending" /* PENDING */,
|
|
@@ -1782,21 +1660,9 @@ var AppointmentService = class extends BaseService {
|
|
|
1782
1660
|
const constraints = [];
|
|
1783
1661
|
constraints.push(where2("patientId", "==", patientId));
|
|
1784
1662
|
constraints.push(where2("status", "in", upcomingStatuses));
|
|
1785
|
-
constraints.push(
|
|
1786
|
-
where2(
|
|
1787
|
-
"appointmentStartTime",
|
|
1788
|
-
">=",
|
|
1789
|
-
Timestamp2.fromDate(effectiveStartDate)
|
|
1790
|
-
)
|
|
1791
|
-
);
|
|
1663
|
+
constraints.push(where2("appointmentStartTime", ">=", Timestamp2.fromDate(effectiveStartDate)));
|
|
1792
1664
|
if (options == null ? void 0 : options.endDate) {
|
|
1793
|
-
constraints.push(
|
|
1794
|
-
where2(
|
|
1795
|
-
"appointmentStartTime",
|
|
1796
|
-
"<=",
|
|
1797
|
-
Timestamp2.fromDate(options.endDate)
|
|
1798
|
-
)
|
|
1799
|
-
);
|
|
1665
|
+
constraints.push(where2("appointmentStartTime", "<=", Timestamp2.fromDate(options.endDate)));
|
|
1800
1666
|
}
|
|
1801
1667
|
constraints.push(orderBy2("appointmentStartTime", "asc"));
|
|
1802
1668
|
if (options == null ? void 0 : options.limit) {
|
|
@@ -1805,14 +1671,9 @@ var AppointmentService = class extends BaseService {
|
|
|
1805
1671
|
if (options == null ? void 0 : options.startAfter) {
|
|
1806
1672
|
constraints.push(startAfter2(options.startAfter));
|
|
1807
1673
|
}
|
|
1808
|
-
const q = query2(
|
|
1809
|
-
collection2(this.db, APPOINTMENTS_COLLECTION),
|
|
1810
|
-
...constraints
|
|
1811
|
-
);
|
|
1674
|
+
const q = query2(collection2(this.db, APPOINTMENTS_COLLECTION), ...constraints);
|
|
1812
1675
|
const querySnapshot = await getDocs2(q);
|
|
1813
|
-
const appointments = querySnapshot.docs.map(
|
|
1814
|
-
(doc38) => doc38.data()
|
|
1815
|
-
);
|
|
1676
|
+
const appointments = querySnapshot.docs.map((doc38) => doc38.data());
|
|
1816
1677
|
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
1817
1678
|
console.log(
|
|
1818
1679
|
`[APPOINTMENT_SERVICE] Found ${appointments.length} upcoming appointments for patient ${patientId}`
|
|
@@ -1837,9 +1698,7 @@ var AppointmentService = class extends BaseService {
|
|
|
1837
1698
|
*/
|
|
1838
1699
|
async getPastPatientAppointments(patientId, options) {
|
|
1839
1700
|
try {
|
|
1840
|
-
console.log(
|
|
1841
|
-
`[APPOINTMENT_SERVICE] Getting past appointments for patient: ${patientId}`
|
|
1842
|
-
);
|
|
1701
|
+
console.log(`[APPOINTMENT_SERVICE] Getting past appointments for patient: ${patientId}`);
|
|
1843
1702
|
const effectiveEndDate = (options == null ? void 0 : options.endDate) || /* @__PURE__ */ new Date();
|
|
1844
1703
|
const pastStatuses = ["completed" /* COMPLETED */];
|
|
1845
1704
|
if (options == null ? void 0 : options.showCanceled) {
|
|
@@ -1857,20 +1716,10 @@ var AppointmentService = class extends BaseService {
|
|
|
1857
1716
|
constraints.push(where2("status", "in", pastStatuses));
|
|
1858
1717
|
if (options == null ? void 0 : options.startDate) {
|
|
1859
1718
|
constraints.push(
|
|
1860
|
-
where2(
|
|
1861
|
-
"appointmentStartTime",
|
|
1862
|
-
">=",
|
|
1863
|
-
Timestamp2.fromDate(options.startDate)
|
|
1864
|
-
)
|
|
1719
|
+
where2("appointmentStartTime", ">=", Timestamp2.fromDate(options.startDate))
|
|
1865
1720
|
);
|
|
1866
1721
|
}
|
|
1867
|
-
constraints.push(
|
|
1868
|
-
where2(
|
|
1869
|
-
"appointmentStartTime",
|
|
1870
|
-
"<=",
|
|
1871
|
-
Timestamp2.fromDate(effectiveEndDate)
|
|
1872
|
-
)
|
|
1873
|
-
);
|
|
1722
|
+
constraints.push(where2("appointmentStartTime", "<=", Timestamp2.fromDate(effectiveEndDate)));
|
|
1874
1723
|
constraints.push(orderBy2("appointmentStartTime", "desc"));
|
|
1875
1724
|
if (options == null ? void 0 : options.limit) {
|
|
1876
1725
|
constraints.push(limit2(options.limit));
|
|
@@ -1878,14 +1727,9 @@ var AppointmentService = class extends BaseService {
|
|
|
1878
1727
|
if (options == null ? void 0 : options.startAfter) {
|
|
1879
1728
|
constraints.push(startAfter2(options.startAfter));
|
|
1880
1729
|
}
|
|
1881
|
-
const q = query2(
|
|
1882
|
-
collection2(this.db, APPOINTMENTS_COLLECTION),
|
|
1883
|
-
...constraints
|
|
1884
|
-
);
|
|
1730
|
+
const q = query2(collection2(this.db, APPOINTMENTS_COLLECTION), ...constraints);
|
|
1885
1731
|
const querySnapshot = await getDocs2(q);
|
|
1886
|
-
const appointments = querySnapshot.docs.map(
|
|
1887
|
-
(doc38) => doc38.data()
|
|
1888
|
-
);
|
|
1732
|
+
const appointments = querySnapshot.docs.map((doc38) => doc38.data());
|
|
1889
1733
|
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
1890
1734
|
console.log(
|
|
1891
1735
|
`[APPOINTMENT_SERVICE] Found ${appointments.length} past appointments for patient ${patientId}`
|
|
@@ -1899,6 +1743,46 @@ var AppointmentService = class extends BaseService {
|
|
|
1899
1743
|
throw error;
|
|
1900
1744
|
}
|
|
1901
1745
|
}
|
|
1746
|
+
/**
|
|
1747
|
+
* Counts completed appointments for a patient with optional clinic filtering.
|
|
1748
|
+
*
|
|
1749
|
+
* @param patientId ID of the patient.
|
|
1750
|
+
* @param clinicBranchId Optional ID of the clinic branch to either include or exclude.
|
|
1751
|
+
* @param excludeClinic Optional boolean. If true (default), excludes the specified clinic. If false, includes only that clinic.
|
|
1752
|
+
* @returns The count of completed appointments.
|
|
1753
|
+
*/
|
|
1754
|
+
async countCompletedAppointments(patientId, clinicBranchId, excludeClinic = true) {
|
|
1755
|
+
try {
|
|
1756
|
+
console.log(
|
|
1757
|
+
`[APPOINTMENT_SERVICE] Counting completed appointments for patient: ${patientId}`,
|
|
1758
|
+
{ clinicBranchId, excludeClinic }
|
|
1759
|
+
);
|
|
1760
|
+
const constraints = [
|
|
1761
|
+
where2("patientId", "==", patientId),
|
|
1762
|
+
where2("status", "==", "completed" /* COMPLETED */)
|
|
1763
|
+
];
|
|
1764
|
+
if (clinicBranchId) {
|
|
1765
|
+
if (excludeClinic) {
|
|
1766
|
+
constraints.push(where2("clinicBranchId", "!=", clinicBranchId));
|
|
1767
|
+
} else {
|
|
1768
|
+
constraints.push(where2("clinicBranchId", "==", clinicBranchId));
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1771
|
+
const q = query2(collection2(this.db, APPOINTMENTS_COLLECTION), ...constraints);
|
|
1772
|
+
const snapshot = await getCountFromServer(q);
|
|
1773
|
+
const count = snapshot.data().count;
|
|
1774
|
+
console.log(
|
|
1775
|
+
`[APPOINTMENT_SERVICE] Found ${count} completed appointments for patient ${patientId}`
|
|
1776
|
+
);
|
|
1777
|
+
return count;
|
|
1778
|
+
} catch (error) {
|
|
1779
|
+
console.error(
|
|
1780
|
+
`[APPOINTMENT_SERVICE] Error counting completed appointments for patient ${patientId}:`,
|
|
1781
|
+
error
|
|
1782
|
+
);
|
|
1783
|
+
throw error;
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1902
1786
|
};
|
|
1903
1787
|
|
|
1904
1788
|
// src/services/auth/auth.service.ts
|
|
@@ -1908,15 +1792,13 @@ import {
|
|
|
1908
1792
|
signInAnonymously as firebaseSignInAnonymously,
|
|
1909
1793
|
signOut as firebaseSignOut,
|
|
1910
1794
|
GoogleAuthProvider,
|
|
1911
|
-
FacebookAuthProvider,
|
|
1912
|
-
OAuthProvider,
|
|
1913
|
-
signInWithPopup,
|
|
1914
1795
|
linkWithCredential,
|
|
1915
1796
|
EmailAuthProvider,
|
|
1916
1797
|
onAuthStateChanged,
|
|
1917
1798
|
sendPasswordResetEmail,
|
|
1918
1799
|
verifyPasswordResetCode,
|
|
1919
|
-
confirmPasswordReset
|
|
1800
|
+
confirmPasswordReset,
|
|
1801
|
+
signInWithCredential
|
|
1920
1802
|
} from "firebase/auth";
|
|
1921
1803
|
import {
|
|
1922
1804
|
collection as collection18,
|
|
@@ -7929,7 +7811,10 @@ var BillingTransactionsService = class extends BaseService {
|
|
|
7929
7811
|
"subscription_reactivated" /* SUBSCRIPTION_REACTIVATED */,
|
|
7930
7812
|
"subscription_deleted" /* SUBSCRIPTION_DELETED */
|
|
7931
7813
|
];
|
|
7932
|
-
const constraints = [
|
|
7814
|
+
const constraints = [
|
|
7815
|
+
where12("type", "in", subscriptionTypes),
|
|
7816
|
+
orderBy5("timestamp", "desc")
|
|
7817
|
+
];
|
|
7933
7818
|
if (startAfterDoc) {
|
|
7934
7819
|
constraints.push(startAfter7(startAfterDoc));
|
|
7935
7820
|
}
|
|
@@ -9993,19 +9878,13 @@ var AuthService = class extends BaseService {
|
|
|
9993
9878
|
constructor(db, auth, app, userService) {
|
|
9994
9879
|
super(db, auth, app);
|
|
9995
9880
|
this.googleProvider = new GoogleAuthProvider();
|
|
9996
|
-
this.facebookProvider = new FacebookAuthProvider();
|
|
9997
|
-
this.appleProvider = new OAuthProvider("apple.com");
|
|
9998
9881
|
this.userService = userService || new UserService(db, auth, app);
|
|
9999
9882
|
}
|
|
10000
9883
|
/**
|
|
10001
9884
|
* Registruje novog korisnika sa email-om i lozinkom
|
|
10002
9885
|
*/
|
|
10003
9886
|
async signUp(email, password, initialRole = "patient" /* PATIENT */, options) {
|
|
10004
|
-
const { user: firebaseUser } = await createUserWithEmailAndPassword(
|
|
10005
|
-
this.auth,
|
|
10006
|
-
email,
|
|
10007
|
-
password
|
|
10008
|
-
);
|
|
9887
|
+
const { user: firebaseUser } = await createUserWithEmailAndPassword(this.auth, email, password);
|
|
10009
9888
|
return this.userService.createUser(firebaseUser, [initialRole], options);
|
|
10010
9889
|
}
|
|
10011
9890
|
/**
|
|
@@ -10024,20 +9903,13 @@ var AuthService = class extends BaseService {
|
|
|
10024
9903
|
await clinicAdminSignupSchema.parseAsync(data);
|
|
10025
9904
|
console.log("[AUTH] Clinic admin signup data validation passed");
|
|
10026
9905
|
} catch (validationError) {
|
|
10027
|
-
console.error(
|
|
10028
|
-
"[AUTH] Validation error in signUpClinicAdmin:",
|
|
10029
|
-
validationError
|
|
10030
|
-
);
|
|
9906
|
+
console.error("[AUTH] Validation error in signUpClinicAdmin:", validationError);
|
|
10031
9907
|
throw validationError;
|
|
10032
9908
|
}
|
|
10033
9909
|
console.log("[AUTH] Creating Firebase user");
|
|
10034
9910
|
let firebaseUser;
|
|
10035
9911
|
try {
|
|
10036
|
-
const result = await createUserWithEmailAndPassword(
|
|
10037
|
-
this.auth,
|
|
10038
|
-
data.email,
|
|
10039
|
-
data.password
|
|
10040
|
-
);
|
|
9912
|
+
const result = await createUserWithEmailAndPassword(this.auth, data.email, data.password);
|
|
10041
9913
|
firebaseUser = result.user;
|
|
10042
9914
|
console.log("[AUTH] Firebase user created successfully", {
|
|
10043
9915
|
uid: firebaseUser.uid
|
|
@@ -10049,13 +9921,9 @@ var AuthService = class extends BaseService {
|
|
|
10049
9921
|
console.log("[AUTH] Creating user with CLINIC_ADMIN role");
|
|
10050
9922
|
let user;
|
|
10051
9923
|
try {
|
|
10052
|
-
user = await this.userService.createUser(
|
|
10053
|
-
|
|
10054
|
-
|
|
10055
|
-
{
|
|
10056
|
-
skipProfileCreation: true
|
|
10057
|
-
}
|
|
10058
|
-
);
|
|
9924
|
+
user = await this.userService.createUser(firebaseUser, ["clinic_admin" /* CLINIC_ADMIN */], {
|
|
9925
|
+
skipProfileCreation: true
|
|
9926
|
+
});
|
|
10059
9927
|
console.log("[AUTH] User with CLINIC_ADMIN role created successfully", {
|
|
10060
9928
|
userId: user.uid
|
|
10061
9929
|
});
|
|
@@ -10072,11 +9940,7 @@ var AuthService = class extends BaseService {
|
|
|
10072
9940
|
};
|
|
10073
9941
|
console.log("[AUTH] Contact person object created");
|
|
10074
9942
|
console.log("[AUTH] Initializing clinic services");
|
|
10075
|
-
const clinicAdminService = new ClinicAdminService(
|
|
10076
|
-
this.db,
|
|
10077
|
-
this.auth,
|
|
10078
|
-
this.app
|
|
10079
|
-
);
|
|
9943
|
+
const clinicAdminService = new ClinicAdminService(this.db, this.auth, this.app);
|
|
10080
9944
|
const clinicGroupService = new ClinicGroupService(
|
|
10081
9945
|
this.db,
|
|
10082
9946
|
this.auth,
|
|
@@ -10093,18 +9957,14 @@ var AuthService = class extends BaseService {
|
|
|
10093
9957
|
mediaService
|
|
10094
9958
|
);
|
|
10095
9959
|
clinicAdminService.setServices(clinicGroupService, clinicService);
|
|
10096
|
-
console.log(
|
|
10097
|
-
"[AUTH] Services initialized and circular dependencies resolved"
|
|
10098
|
-
);
|
|
9960
|
+
console.log("[AUTH] Services initialized and circular dependencies resolved");
|
|
10099
9961
|
let clinicGroup = null;
|
|
10100
9962
|
let adminProfile = null;
|
|
10101
9963
|
if (data.isCreatingNewGroup) {
|
|
10102
9964
|
console.log("[AUTH] Creating new clinic group flow");
|
|
10103
9965
|
if (!data.clinicGroupData) {
|
|
10104
9966
|
console.error("[AUTH] Clinic group data is missing");
|
|
10105
|
-
throw new Error(
|
|
10106
|
-
"Clinic group data is required when creating a new group"
|
|
10107
|
-
);
|
|
9967
|
+
throw new Error("Clinic group data is required when creating a new group");
|
|
10108
9968
|
}
|
|
10109
9969
|
console.log("[AUTH] Creating clinic admin first (without group)");
|
|
10110
9970
|
const createClinicAdminData = {
|
|
@@ -10117,17 +9977,12 @@ var AuthService = class extends BaseService {
|
|
|
10117
9977
|
// No clinicGroupId yet
|
|
10118
9978
|
};
|
|
10119
9979
|
try {
|
|
10120
|
-
adminProfile = await clinicAdminService.createClinicAdmin(
|
|
10121
|
-
createClinicAdminData
|
|
10122
|
-
);
|
|
9980
|
+
adminProfile = await clinicAdminService.createClinicAdmin(createClinicAdminData);
|
|
10123
9981
|
console.log("[AUTH] Clinic admin created successfully", {
|
|
10124
9982
|
adminId: adminProfile.id
|
|
10125
9983
|
});
|
|
10126
9984
|
} catch (adminCreationError) {
|
|
10127
|
-
console.error(
|
|
10128
|
-
"[AUTH] Clinic admin creation failed:",
|
|
10129
|
-
adminCreationError
|
|
10130
|
-
);
|
|
9985
|
+
console.error("[AUTH] Clinic admin creation failed:", adminCreationError);
|
|
10131
9986
|
throw adminCreationError;
|
|
10132
9987
|
}
|
|
10133
9988
|
try {
|
|
@@ -10135,14 +9990,9 @@ var AuthService = class extends BaseService {
|
|
|
10135
9990
|
user = await this.userService.updateUser(firebaseUser.uid, {
|
|
10136
9991
|
adminProfile: adminProfile.id
|
|
10137
9992
|
});
|
|
10138
|
-
console.log(
|
|
10139
|
-
"[AUTH] User updated with admin profile reference successfully"
|
|
10140
|
-
);
|
|
9993
|
+
console.log("[AUTH] User updated with admin profile reference successfully");
|
|
10141
9994
|
} catch (userUpdateError) {
|
|
10142
|
-
console.error(
|
|
10143
|
-
"[AUTH] Failed to update user with admin profile:",
|
|
10144
|
-
userUpdateError
|
|
10145
|
-
);
|
|
9995
|
+
console.error("[AUTH] Failed to update user with admin profile:", userUpdateError);
|
|
10146
9996
|
throw userUpdateError;
|
|
10147
9997
|
}
|
|
10148
9998
|
const createClinicGroupData = {
|
|
@@ -10180,23 +10030,16 @@ var AuthService = class extends BaseService {
|
|
|
10180
10030
|
clinicGroupId: clinicGroup.id
|
|
10181
10031
|
});
|
|
10182
10032
|
console.log("[AUTH] Admin updated with clinic group ID successfully");
|
|
10183
|
-
adminProfile = await clinicAdminService.getClinicAdmin(
|
|
10184
|
-
adminProfile.id
|
|
10185
|
-
);
|
|
10033
|
+
adminProfile = await clinicAdminService.getClinicAdmin(adminProfile.id);
|
|
10186
10034
|
} catch (groupCreationError) {
|
|
10187
|
-
console.error(
|
|
10188
|
-
"[AUTH] Clinic group creation failed:",
|
|
10189
|
-
groupCreationError
|
|
10190
|
-
);
|
|
10035
|
+
console.error("[AUTH] Clinic group creation failed:", groupCreationError);
|
|
10191
10036
|
throw groupCreationError;
|
|
10192
10037
|
}
|
|
10193
10038
|
} else {
|
|
10194
10039
|
console.log("[AUTH] Joining existing clinic group flow");
|
|
10195
10040
|
if (!data.inviteToken) {
|
|
10196
10041
|
console.error("[AUTH] Invite token is missing");
|
|
10197
|
-
throw new Error(
|
|
10198
|
-
"Invite token is required when joining an existing group"
|
|
10199
|
-
);
|
|
10042
|
+
throw new Error("Invite token is required when joining an existing group");
|
|
10200
10043
|
}
|
|
10201
10044
|
console.log("[AUTH] Invite token provided", {
|
|
10202
10045
|
token: data.inviteToken
|
|
@@ -10207,11 +10050,7 @@ var AuthService = class extends BaseService {
|
|
|
10207
10050
|
const querySnapshot = await getDocs18(q);
|
|
10208
10051
|
let foundGroup = null;
|
|
10209
10052
|
let foundToken = null;
|
|
10210
|
-
console.log(
|
|
10211
|
-
"[AUTH] Found",
|
|
10212
|
-
querySnapshot.size,
|
|
10213
|
-
"clinic groups to check"
|
|
10214
|
-
);
|
|
10053
|
+
console.log("[AUTH] Found", querySnapshot.size, "clinic groups to check");
|
|
10215
10054
|
for (const docSnapshot of querySnapshot.docs) {
|
|
10216
10055
|
const group = docSnapshot.data();
|
|
10217
10056
|
console.log("[AUTH] Checking group", {
|
|
@@ -10257,17 +10096,12 @@ var AuthService = class extends BaseService {
|
|
|
10257
10096
|
isActive: true
|
|
10258
10097
|
};
|
|
10259
10098
|
try {
|
|
10260
|
-
adminProfile = await clinicAdminService.createClinicAdmin(
|
|
10261
|
-
createClinicAdminData
|
|
10262
|
-
);
|
|
10099
|
+
adminProfile = await clinicAdminService.createClinicAdmin(createClinicAdminData);
|
|
10263
10100
|
console.log("[AUTH] Clinic admin created successfully", {
|
|
10264
10101
|
adminId: adminProfile.id
|
|
10265
10102
|
});
|
|
10266
10103
|
} catch (adminCreationError) {
|
|
10267
|
-
console.error(
|
|
10268
|
-
"[AUTH] Clinic admin creation failed:",
|
|
10269
|
-
adminCreationError
|
|
10270
|
-
);
|
|
10104
|
+
console.error("[AUTH] Clinic admin creation failed:", adminCreationError);
|
|
10271
10105
|
throw adminCreationError;
|
|
10272
10106
|
}
|
|
10273
10107
|
try {
|
|
@@ -10288,9 +10122,7 @@ var AuthService = class extends BaseService {
|
|
|
10288
10122
|
clinicAdminId: (adminProfile == null ? void 0 : adminProfile.id) || "unknown"
|
|
10289
10123
|
});
|
|
10290
10124
|
if (!clinicGroup || !adminProfile) {
|
|
10291
|
-
throw new Error(
|
|
10292
|
-
"Failed to create or retrieve clinic group or admin profile"
|
|
10293
|
-
);
|
|
10125
|
+
throw new Error("Failed to create or retrieve clinic group or admin profile");
|
|
10294
10126
|
}
|
|
10295
10127
|
return {
|
|
10296
10128
|
user,
|
|
@@ -10318,11 +10150,7 @@ var AuthService = class extends BaseService {
|
|
|
10318
10150
|
* Prijavljuje korisnika sa email-om i lozinkom
|
|
10319
10151
|
*/
|
|
10320
10152
|
async signIn(email, password) {
|
|
10321
|
-
const { user: firebaseUser } = await signInWithEmailAndPassword(
|
|
10322
|
-
this.auth,
|
|
10323
|
-
email,
|
|
10324
|
-
password
|
|
10325
|
-
);
|
|
10153
|
+
const { user: firebaseUser } = await signInWithEmailAndPassword(this.auth, email, password);
|
|
10326
10154
|
return this.userService.getOrCreateUser(firebaseUser);
|
|
10327
10155
|
}
|
|
10328
10156
|
/**
|
|
@@ -10336,11 +10164,7 @@ var AuthService = class extends BaseService {
|
|
|
10336
10164
|
async signInClinicAdmin(email, password) {
|
|
10337
10165
|
var _a;
|
|
10338
10166
|
try {
|
|
10339
|
-
const clinicAdminService = new ClinicAdminService(
|
|
10340
|
-
this.db,
|
|
10341
|
-
this.auth,
|
|
10342
|
-
this.app
|
|
10343
|
-
);
|
|
10167
|
+
const clinicAdminService = new ClinicAdminService(this.db, this.auth, this.app);
|
|
10344
10168
|
const clinicGroupService = new ClinicGroupService(
|
|
10345
10169
|
this.db,
|
|
10346
10170
|
this.auth,
|
|
@@ -10357,11 +10181,7 @@ var AuthService = class extends BaseService {
|
|
|
10357
10181
|
mediaService
|
|
10358
10182
|
);
|
|
10359
10183
|
clinicAdminService.setServices(clinicGroupService, clinicService);
|
|
10360
|
-
const { user: firebaseUser } = await signInWithEmailAndPassword(
|
|
10361
|
-
this.auth,
|
|
10362
|
-
email,
|
|
10363
|
-
password
|
|
10364
|
-
);
|
|
10184
|
+
const { user: firebaseUser } = await signInWithEmailAndPassword(this.auth, email, password);
|
|
10365
10185
|
const user = await this.userService.getOrCreateUser(firebaseUser);
|
|
10366
10186
|
if (!((_a = user.roles) == null ? void 0 : _a.includes("clinic_admin" /* CLINIC_ADMIN */))) {
|
|
10367
10187
|
console.error("[AUTH] User is not a clinic admin:", user.uid);
|
|
@@ -10371,21 +10191,14 @@ var AuthService = class extends BaseService {
|
|
|
10371
10191
|
console.error("[AUTH] User has no admin profile:", user.uid);
|
|
10372
10192
|
throw AUTH_ERRORS.NOT_FOUND;
|
|
10373
10193
|
}
|
|
10374
|
-
const adminProfile = await clinicAdminService.getClinicAdmin(
|
|
10375
|
-
user.adminProfile
|
|
10376
|
-
);
|
|
10194
|
+
const adminProfile = await clinicAdminService.getClinicAdmin(user.adminProfile);
|
|
10377
10195
|
if (!adminProfile) {
|
|
10378
10196
|
console.error("[AUTH] Admin profile not found:", user.adminProfile);
|
|
10379
10197
|
throw AUTH_ERRORS.NOT_FOUND;
|
|
10380
10198
|
}
|
|
10381
|
-
const clinicGroup = await clinicGroupService.getClinicGroup(
|
|
10382
|
-
adminProfile.clinicGroupId
|
|
10383
|
-
);
|
|
10199
|
+
const clinicGroup = await clinicGroupService.getClinicGroup(adminProfile.clinicGroupId);
|
|
10384
10200
|
if (!clinicGroup) {
|
|
10385
|
-
console.error(
|
|
10386
|
-
"[AUTH] Clinic group not found:",
|
|
10387
|
-
adminProfile.clinicGroupId
|
|
10388
|
-
);
|
|
10201
|
+
console.error("[AUTH] Clinic group not found:", adminProfile.clinicGroupId);
|
|
10389
10202
|
throw AUTH_ERRORS.NOT_FOUND;
|
|
10390
10203
|
}
|
|
10391
10204
|
return {
|
|
@@ -10398,39 +10211,6 @@ var AuthService = class extends BaseService {
|
|
|
10398
10211
|
throw error;
|
|
10399
10212
|
}
|
|
10400
10213
|
}
|
|
10401
|
-
/**
|
|
10402
|
-
* Prijavljuje korisnika sa Facebook-om
|
|
10403
|
-
*/
|
|
10404
|
-
async signInWithFacebook() {
|
|
10405
|
-
const provider = new FacebookAuthProvider();
|
|
10406
|
-
const { user: firebaseUser } = await signInWithPopup(this.auth, provider);
|
|
10407
|
-
return this.userService.getOrCreateUser(firebaseUser);
|
|
10408
|
-
}
|
|
10409
|
-
/**
|
|
10410
|
-
* Prijavljuje korisnika sa Google nalogom
|
|
10411
|
-
*/
|
|
10412
|
-
async signInWithGoogle(initialRole = "patient" /* PATIENT */, options) {
|
|
10413
|
-
const { user: firebaseUser } = await signInWithPopup(
|
|
10414
|
-
this.auth,
|
|
10415
|
-
this.googleProvider
|
|
10416
|
-
);
|
|
10417
|
-
const existingUser = await this.userService.getUserByEmail(
|
|
10418
|
-
firebaseUser.email
|
|
10419
|
-
);
|
|
10420
|
-
if (existingUser) {
|
|
10421
|
-
await this.userService.updateUserLoginTimestamp(existingUser.uid);
|
|
10422
|
-
return existingUser;
|
|
10423
|
-
}
|
|
10424
|
-
return this.userService.createUser(firebaseUser, [initialRole], options);
|
|
10425
|
-
}
|
|
10426
|
-
/**
|
|
10427
|
-
* Prijavljuje korisnika sa Apple-om
|
|
10428
|
-
*/
|
|
10429
|
-
async signInWithApple() {
|
|
10430
|
-
const provider = new OAuthProvider("apple.com");
|
|
10431
|
-
const { user: firebaseUser } = await signInWithPopup(this.auth, provider);
|
|
10432
|
-
return this.userService.getOrCreateUser(firebaseUser);
|
|
10433
|
-
}
|
|
10434
10214
|
/**
|
|
10435
10215
|
* Prijavljuje korisnika anonimno
|
|
10436
10216
|
*/
|
|
@@ -10467,18 +10247,11 @@ var AuthService = class extends BaseService {
|
|
|
10467
10247
|
throw AUTH_ERRORS.NOT_AUTHENTICATED;
|
|
10468
10248
|
}
|
|
10469
10249
|
if (!currentUser.isAnonymous) {
|
|
10470
|
-
throw new AuthError(
|
|
10471
|
-
"User is not anonymous",
|
|
10472
|
-
"AUTH/NOT_ANONYMOUS_USER",
|
|
10473
|
-
400
|
|
10474
|
-
);
|
|
10250
|
+
throw new AuthError("User is not anonymous", "AUTH/NOT_ANONYMOUS_USER", 400);
|
|
10475
10251
|
}
|
|
10476
10252
|
const credential = EmailAuthProvider.credential(email, password);
|
|
10477
10253
|
await linkWithCredential(currentUser, credential);
|
|
10478
|
-
return await this.userService.upgradeAnonymousUser(
|
|
10479
|
-
currentUser.uid,
|
|
10480
|
-
email
|
|
10481
|
-
);
|
|
10254
|
+
return await this.userService.upgradeAnonymousUser(currentUser.uid, email);
|
|
10482
10255
|
} catch (error) {
|
|
10483
10256
|
if (error instanceof z23.ZodError) {
|
|
10484
10257
|
throw AUTH_ERRORS.VALIDATION_ERROR;
|
|
@@ -10490,109 +10263,6 @@ var AuthService = class extends BaseService {
|
|
|
10490
10263
|
throw error;
|
|
10491
10264
|
}
|
|
10492
10265
|
}
|
|
10493
|
-
/**
|
|
10494
|
-
* Upgrades an anonymous user to a regular user by signing in with a Google account.
|
|
10495
|
-
*
|
|
10496
|
-
* @throws {AuthError} If the user is not anonymous.
|
|
10497
|
-
* @throws {AuthError} If the user is not authenticated.
|
|
10498
|
-
* @throws {AuthError} If the popup window is closed by the user.
|
|
10499
|
-
* @throws {FirebaseError} If any other Firebase error occurs.
|
|
10500
|
-
*
|
|
10501
|
-
* @returns {Promise<User>} The upgraded user.
|
|
10502
|
-
*/
|
|
10503
|
-
async upgradeAnonymousUserWithGoogle() {
|
|
10504
|
-
try {
|
|
10505
|
-
const currentUser = this.auth.currentUser;
|
|
10506
|
-
if (!currentUser) {
|
|
10507
|
-
throw AUTH_ERRORS.NOT_AUTHENTICATED;
|
|
10508
|
-
}
|
|
10509
|
-
if (!currentUser.isAnonymous) {
|
|
10510
|
-
throw new AuthError(
|
|
10511
|
-
"User is not anonymous",
|
|
10512
|
-
"AUTH/NOT_ANONYMOUS_USER",
|
|
10513
|
-
400
|
|
10514
|
-
);
|
|
10515
|
-
}
|
|
10516
|
-
const userCredential = await signInWithPopup(
|
|
10517
|
-
this.auth,
|
|
10518
|
-
this.googleProvider
|
|
10519
|
-
);
|
|
10520
|
-
if (!userCredential) throw AUTH_ERRORS.INVALID_CREDENTIAL;
|
|
10521
|
-
return await this.userService.upgradeAnonymousUser(
|
|
10522
|
-
currentUser.uid,
|
|
10523
|
-
userCredential.user.email
|
|
10524
|
-
);
|
|
10525
|
-
} catch (error) {
|
|
10526
|
-
const firebaseError = error;
|
|
10527
|
-
if (firebaseError.code === "auth/popup-closed-by-user" /* POPUP_CLOSED_BY_USER */) {
|
|
10528
|
-
throw AUTH_ERRORS.POPUP_CLOSED;
|
|
10529
|
-
}
|
|
10530
|
-
throw error;
|
|
10531
|
-
}
|
|
10532
|
-
}
|
|
10533
|
-
async upgradeAnonymousUserWithFacebook() {
|
|
10534
|
-
try {
|
|
10535
|
-
const currentUser = this.auth.currentUser;
|
|
10536
|
-
if (!currentUser) {
|
|
10537
|
-
throw AUTH_ERRORS.NOT_AUTHENTICATED;
|
|
10538
|
-
}
|
|
10539
|
-
if (!currentUser.isAnonymous) {
|
|
10540
|
-
throw new AuthError(
|
|
10541
|
-
"User is not anonymous",
|
|
10542
|
-
"AUTH/NOT_ANONYMOUS_USER",
|
|
10543
|
-
400
|
|
10544
|
-
);
|
|
10545
|
-
}
|
|
10546
|
-
this.facebookProvider.addScope("email");
|
|
10547
|
-
const userCredential = await signInWithPopup(
|
|
10548
|
-
this.auth,
|
|
10549
|
-
this.facebookProvider
|
|
10550
|
-
);
|
|
10551
|
-
if (!userCredential) throw AUTH_ERRORS.INVALID_CREDENTIAL;
|
|
10552
|
-
return await this.userService.upgradeAnonymousUser(
|
|
10553
|
-
currentUser.uid,
|
|
10554
|
-
userCredential.user.email
|
|
10555
|
-
);
|
|
10556
|
-
} catch (error) {
|
|
10557
|
-
const firebaseError = error;
|
|
10558
|
-
if (firebaseError.code === "auth/popup-closed-by-user" /* POPUP_CLOSED_BY_USER */) {
|
|
10559
|
-
throw AUTH_ERRORS.POPUP_CLOSED;
|
|
10560
|
-
}
|
|
10561
|
-
throw error;
|
|
10562
|
-
}
|
|
10563
|
-
}
|
|
10564
|
-
async upgradeAnonymousUserWithApple() {
|
|
10565
|
-
try {
|
|
10566
|
-
const currentUser = this.auth.currentUser;
|
|
10567
|
-
if (!currentUser) {
|
|
10568
|
-
throw AUTH_ERRORS.NOT_AUTHENTICATED;
|
|
10569
|
-
}
|
|
10570
|
-
if (!currentUser.isAnonymous) {
|
|
10571
|
-
throw new AuthError(
|
|
10572
|
-
"User is not anonymous",
|
|
10573
|
-
"AUTH/NOT_ANONYMOUS_USER",
|
|
10574
|
-
400
|
|
10575
|
-
);
|
|
10576
|
-
}
|
|
10577
|
-
this.appleProvider.addScope("email");
|
|
10578
|
-
this.appleProvider.addScope("name");
|
|
10579
|
-
const userCredential = await signInWithPopup(
|
|
10580
|
-
this.auth,
|
|
10581
|
-
this.appleProvider
|
|
10582
|
-
);
|
|
10583
|
-
if (!userCredential) throw AUTH_ERRORS.INVALID_CREDENTIAL;
|
|
10584
|
-
return await this.userService.upgradeAnonymousUser(
|
|
10585
|
-
currentUser.uid,
|
|
10586
|
-
userCredential.user.email
|
|
10587
|
-
);
|
|
10588
|
-
} catch (error) {
|
|
10589
|
-
const firebaseError = error;
|
|
10590
|
-
if (firebaseError.code === "auth/popup-closed-by-user" /* POPUP_CLOSED_BY_USER */) {
|
|
10591
|
-
throw AUTH_ERRORS.POPUP_CLOSED;
|
|
10592
|
-
}
|
|
10593
|
-
throw error;
|
|
10594
|
-
}
|
|
10595
|
-
}
|
|
10596
10266
|
/**
|
|
10597
10267
|
* Šalje email za resetovanje lozinke korisniku
|
|
10598
10268
|
* @param email Email adresa korisnika
|
|
@@ -10673,11 +10343,7 @@ var AuthService = class extends BaseService {
|
|
|
10673
10343
|
await this.validateSignupData(data);
|
|
10674
10344
|
console.log("[AUTH] Creating Firebase user");
|
|
10675
10345
|
try {
|
|
10676
|
-
const result = await createUserWithEmailAndPassword(
|
|
10677
|
-
this.auth,
|
|
10678
|
-
data.email,
|
|
10679
|
-
data.password
|
|
10680
|
-
);
|
|
10346
|
+
const result = await createUserWithEmailAndPassword(this.auth, data.email, data.password);
|
|
10681
10347
|
firebaseUser = result.user;
|
|
10682
10348
|
console.log("[AUTH] Firebase user created successfully", {
|
|
10683
10349
|
uid: firebaseUser.uid
|
|
@@ -10687,64 +10353,43 @@ var AuthService = class extends BaseService {
|
|
|
10687
10353
|
throw handleFirebaseError(firebaseError);
|
|
10688
10354
|
}
|
|
10689
10355
|
console.log("[AUTH] Starting Firestore transaction");
|
|
10690
|
-
const transactionResult = await runTransaction(
|
|
10691
|
-
|
|
10692
|
-
|
|
10693
|
-
|
|
10694
|
-
|
|
10695
|
-
|
|
10696
|
-
|
|
10697
|
-
|
|
10698
|
-
|
|
10699
|
-
|
|
10700
|
-
|
|
10701
|
-
|
|
10702
|
-
|
|
10703
|
-
firebaseUser,
|
|
10704
|
-
["practitioner" /* PRACTITIONER */],
|
|
10705
|
-
{ skipProfileCreation: true }
|
|
10356
|
+
const transactionResult = await runTransaction(this.db, async (transaction) => {
|
|
10357
|
+
console.log("[AUTH] Transaction started - creating user and practitioner");
|
|
10358
|
+
const practitionerService = new PractitionerService(this.db, this.auth, this.app);
|
|
10359
|
+
console.log("[AUTH] Creating user document");
|
|
10360
|
+
const user = await this.userService.createUser(firebaseUser, ["practitioner" /* PRACTITIONER */], {
|
|
10361
|
+
skipProfileCreation: true
|
|
10362
|
+
});
|
|
10363
|
+
let practitioner;
|
|
10364
|
+
if (data.token) {
|
|
10365
|
+
console.log("[AUTH] Claiming existing practitioner profile with token");
|
|
10366
|
+
const claimedPractitioner = await practitionerService.validateTokenAndClaimProfile(
|
|
10367
|
+
data.token,
|
|
10368
|
+
firebaseUser.uid
|
|
10706
10369
|
);
|
|
10707
|
-
|
|
10708
|
-
|
|
10709
|
-
console.log(
|
|
10710
|
-
"[AUTH] Claiming existing practitioner profile with token"
|
|
10711
|
-
);
|
|
10712
|
-
const claimedPractitioner = await practitionerService.validateTokenAndClaimProfile(
|
|
10713
|
-
data.token,
|
|
10714
|
-
firebaseUser.uid
|
|
10715
|
-
);
|
|
10716
|
-
if (!claimedPractitioner) {
|
|
10717
|
-
throw new Error("Invalid or expired invitation token");
|
|
10718
|
-
}
|
|
10719
|
-
practitioner = claimedPractitioner;
|
|
10720
|
-
} else {
|
|
10721
|
-
console.log("[AUTH] Creating new practitioner profile");
|
|
10722
|
-
const practitionerData = buildPractitionerData(
|
|
10723
|
-
data,
|
|
10724
|
-
firebaseUser.uid
|
|
10725
|
-
);
|
|
10726
|
-
practitioner = await practitionerService.createPractitioner(
|
|
10727
|
-
practitionerData
|
|
10728
|
-
);
|
|
10370
|
+
if (!claimedPractitioner) {
|
|
10371
|
+
throw new Error("Invalid or expired invitation token");
|
|
10729
10372
|
}
|
|
10730
|
-
|
|
10731
|
-
|
|
10732
|
-
|
|
10733
|
-
|
|
10734
|
-
|
|
10735
|
-
return { user, practitioner };
|
|
10373
|
+
practitioner = claimedPractitioner;
|
|
10374
|
+
} else {
|
|
10375
|
+
console.log("[AUTH] Creating new practitioner profile");
|
|
10376
|
+
const practitionerData = buildPractitionerData(data, firebaseUser.uid);
|
|
10377
|
+
practitioner = await practitionerService.createPractitioner(practitionerData);
|
|
10736
10378
|
}
|
|
10737
|
-
|
|
10379
|
+
console.log("[AUTH] Linking practitioner to user");
|
|
10380
|
+
await this.userService.updateUser(firebaseUser.uid, {
|
|
10381
|
+
practitionerProfile: practitioner.id
|
|
10382
|
+
});
|
|
10383
|
+
console.log("[AUTH] Transaction operations completed successfully");
|
|
10384
|
+
return { user, practitioner };
|
|
10385
|
+
});
|
|
10738
10386
|
console.log("[AUTH] Atomic practitioner signup completed successfully", {
|
|
10739
10387
|
userId: transactionResult.user.uid,
|
|
10740
10388
|
practitionerId: transactionResult.practitioner.id
|
|
10741
10389
|
});
|
|
10742
10390
|
return transactionResult;
|
|
10743
10391
|
} catch (error) {
|
|
10744
|
-
console.error(
|
|
10745
|
-
"[AUTH] Atomic signup failed, initiating cleanup...",
|
|
10746
|
-
error
|
|
10747
|
-
);
|
|
10392
|
+
console.error("[AUTH] Atomic signup failed, initiating cleanup...", error);
|
|
10748
10393
|
if (firebaseUser) {
|
|
10749
10394
|
await cleanupFirebaseUser(firebaseUser);
|
|
10750
10395
|
}
|
|
@@ -10767,14 +10412,8 @@ var AuthService = class extends BaseService {
|
|
|
10767
10412
|
}
|
|
10768
10413
|
console.log("[AUTH] Email availability confirmed");
|
|
10769
10414
|
if (data.token) {
|
|
10770
|
-
const practitionerService = new PractitionerService(
|
|
10771
|
-
|
|
10772
|
-
this.auth,
|
|
10773
|
-
this.app
|
|
10774
|
-
);
|
|
10775
|
-
const isValidToken = await practitionerService.validateToken(
|
|
10776
|
-
data.token
|
|
10777
|
-
);
|
|
10415
|
+
const practitionerService = new PractitionerService(this.db, this.auth, this.app);
|
|
10416
|
+
const isValidToken = await practitionerService.validateToken(data.token);
|
|
10778
10417
|
if (!isValidToken) {
|
|
10779
10418
|
console.log("[AUTH] Invalid token provided:", data.token);
|
|
10780
10419
|
throw new Error("Invalid or expired invitation token");
|
|
@@ -10805,16 +10444,8 @@ var AuthService = class extends BaseService {
|
|
|
10805
10444
|
console.log("[AUTH] Starting practitioner signin process", {
|
|
10806
10445
|
email
|
|
10807
10446
|
});
|
|
10808
|
-
const practitionerService = new PractitionerService(
|
|
10809
|
-
|
|
10810
|
-
this.auth,
|
|
10811
|
-
this.app
|
|
10812
|
-
);
|
|
10813
|
-
const { user: firebaseUser } = await signInWithEmailAndPassword(
|
|
10814
|
-
this.auth,
|
|
10815
|
-
email,
|
|
10816
|
-
password
|
|
10817
|
-
);
|
|
10447
|
+
const practitionerService = new PractitionerService(this.db, this.auth, this.app);
|
|
10448
|
+
const { user: firebaseUser } = await signInWithEmailAndPassword(this.auth, email, password);
|
|
10818
10449
|
const user = await this.userService.getOrCreateUser(firebaseUser);
|
|
10819
10450
|
console.log("[AUTH] User retrieved", { uid: user.uid });
|
|
10820
10451
|
if (!((_a = user.roles) == null ? void 0 : _a.includes("practitioner" /* PRACTITIONER */))) {
|
|
@@ -10825,14 +10456,9 @@ var AuthService = class extends BaseService {
|
|
|
10825
10456
|
console.error("[AUTH] User has no practitioner profile:", user.uid);
|
|
10826
10457
|
throw AUTH_ERRORS.NOT_FOUND;
|
|
10827
10458
|
}
|
|
10828
|
-
const practitioner = await practitionerService.getPractitioner(
|
|
10829
|
-
user.practitionerProfile
|
|
10830
|
-
);
|
|
10459
|
+
const practitioner = await practitionerService.getPractitioner(user.practitionerProfile);
|
|
10831
10460
|
if (!practitioner) {
|
|
10832
|
-
console.error(
|
|
10833
|
-
"[AUTH] Practitioner profile not found:",
|
|
10834
|
-
user.practitionerProfile
|
|
10835
|
-
);
|
|
10461
|
+
console.error("[AUTH] Practitioner profile not found:", user.practitionerProfile);
|
|
10836
10462
|
throw AUTH_ERRORS.NOT_FOUND;
|
|
10837
10463
|
}
|
|
10838
10464
|
console.log("[AUTH] Practitioner signin completed successfully", {
|
|
@@ -10848,6 +10474,64 @@ var AuthService = class extends BaseService {
|
|
|
10848
10474
|
throw error;
|
|
10849
10475
|
}
|
|
10850
10476
|
}
|
|
10477
|
+
/**
|
|
10478
|
+
* Signs in a user with a Google ID token from a mobile client.
|
|
10479
|
+
* If the user does not exist, a new user is created.
|
|
10480
|
+
* @param idToken - The Google ID token obtained from the mobile app.
|
|
10481
|
+
* @param initialRole - The role to assign to the user if they are being created.
|
|
10482
|
+
* @returns The signed-in or newly created user.
|
|
10483
|
+
*/
|
|
10484
|
+
async signInWithGoogleIdToken(idToken, initialRole = "patient" /* PATIENT */) {
|
|
10485
|
+
try {
|
|
10486
|
+
console.log("[AUTH] Signing in with Google ID Token");
|
|
10487
|
+
const credential = GoogleAuthProvider.credential(idToken);
|
|
10488
|
+
const { user: firebaseUser } = await signInWithCredential(this.auth, credential);
|
|
10489
|
+
console.log("[AUTH] Firebase user signed in:", firebaseUser.uid);
|
|
10490
|
+
const existingUser = await this.userService.getUserById(firebaseUser.uid);
|
|
10491
|
+
if (existingUser) {
|
|
10492
|
+
console.log("[AUTH] Existing user found, returning profile:", existingUser.uid);
|
|
10493
|
+
return existingUser;
|
|
10494
|
+
}
|
|
10495
|
+
console.log("[AUTH] No existing user found, creating new profile for:", firebaseUser.uid);
|
|
10496
|
+
return this.userService.createUser(firebaseUser, [initialRole]);
|
|
10497
|
+
} catch (error) {
|
|
10498
|
+
console.error("[AUTH] Error in signInWithGoogleIdToken:", error);
|
|
10499
|
+
throw handleFirebaseError(error);
|
|
10500
|
+
}
|
|
10501
|
+
}
|
|
10502
|
+
/**
|
|
10503
|
+
* Links a Google account to the currently signed-in user using an ID token.
|
|
10504
|
+
* This is used to upgrade an anonymous user or to allow an existing user
|
|
10505
|
+
* to sign in with Google in the future.
|
|
10506
|
+
* @param idToken - The Google ID token obtained from the mobile app.
|
|
10507
|
+
* @returns The updated user profile.
|
|
10508
|
+
*/
|
|
10509
|
+
async linkGoogleAccount(idToken) {
|
|
10510
|
+
try {
|
|
10511
|
+
console.log("[AUTH] Linking Google account with ID Token");
|
|
10512
|
+
const currentUser = this.auth.currentUser;
|
|
10513
|
+
if (!currentUser) {
|
|
10514
|
+
throw AUTH_ERRORS.NOT_AUTHENTICATED;
|
|
10515
|
+
}
|
|
10516
|
+
const wasAnonymous = currentUser.isAnonymous;
|
|
10517
|
+
console.log(`[AUTH] Current user is ${wasAnonymous ? "anonymous" : "not anonymous"}`);
|
|
10518
|
+
const credential = GoogleAuthProvider.credential(idToken);
|
|
10519
|
+
const userCredential = await linkWithCredential(currentUser, credential);
|
|
10520
|
+
const linkedFirebaseUser = userCredential.user;
|
|
10521
|
+
console.log("[AUTH] Google account linked successfully to user:", linkedFirebaseUser.uid);
|
|
10522
|
+
if (wasAnonymous) {
|
|
10523
|
+
console.log("[AUTH] Upgrading anonymous user profile");
|
|
10524
|
+
return await this.userService.upgradeAnonymousUser(
|
|
10525
|
+
linkedFirebaseUser.uid,
|
|
10526
|
+
linkedFirebaseUser.email
|
|
10527
|
+
);
|
|
10528
|
+
}
|
|
10529
|
+
return await this.userService.getUserById(linkedFirebaseUser.uid);
|
|
10530
|
+
} catch (error) {
|
|
10531
|
+
console.error("[AUTH] Error in linkGoogleAccount:", error);
|
|
10532
|
+
throw handleFirebaseError(error);
|
|
10533
|
+
}
|
|
10534
|
+
}
|
|
10851
10535
|
};
|
|
10852
10536
|
|
|
10853
10537
|
// src/services/calendar/calendar.v2.service.ts
|
|
@@ -14176,7 +13860,7 @@ import {
|
|
|
14176
13860
|
limit as limit13,
|
|
14177
13861
|
startAfter as startAfter11
|
|
14178
13862
|
} from "firebase/firestore";
|
|
14179
|
-
import { getCountFromServer } from "firebase/firestore";
|
|
13863
|
+
import { getCountFromServer as getCountFromServer2 } from "firebase/firestore";
|
|
14180
13864
|
var DocumentationTemplateService = class extends BaseService {
|
|
14181
13865
|
constructor(...args) {
|
|
14182
13866
|
super(...args);
|
|
@@ -14434,7 +14118,7 @@ var DocumentationTemplateService = class extends BaseService {
|
|
|
14434
14118
|
constraints.push(where26("sortingOrder", "==", sortingOrder));
|
|
14435
14119
|
}
|
|
14436
14120
|
const q = query26(this.collectionRef, ...constraints.filter((c) => c));
|
|
14437
|
-
const snapshot = await
|
|
14121
|
+
const snapshot = await getCountFromServer2(q);
|
|
14438
14122
|
return snapshot.data().count;
|
|
14439
14123
|
}
|
|
14440
14124
|
/**
|
|
@@ -16819,7 +16503,7 @@ import {
|
|
|
16819
16503
|
limit as limit17,
|
|
16820
16504
|
orderBy as orderBy19,
|
|
16821
16505
|
startAfter as startAfter15,
|
|
16822
|
-
getCountFromServer as
|
|
16506
|
+
getCountFromServer as getCountFromServer3
|
|
16823
16507
|
} from "firebase/firestore";
|
|
16824
16508
|
|
|
16825
16509
|
// src/backoffice/types/brand.types.ts
|
|
@@ -16895,7 +16579,7 @@ var BrandService = class extends BaseService {
|
|
|
16895
16579
|
);
|
|
16896
16580
|
}
|
|
16897
16581
|
const q = query32(this.getBrandsRef(), ...constraints);
|
|
16898
|
-
const snapshot = await
|
|
16582
|
+
const snapshot = await getCountFromServer3(q);
|
|
16899
16583
|
return snapshot.data().count;
|
|
16900
16584
|
}
|
|
16901
16585
|
/**
|
|
@@ -16957,7 +16641,7 @@ import {
|
|
|
16957
16641
|
addDoc as addDoc4,
|
|
16958
16642
|
collection as collection33,
|
|
16959
16643
|
doc as doc33,
|
|
16960
|
-
getCountFromServer as
|
|
16644
|
+
getCountFromServer as getCountFromServer4,
|
|
16961
16645
|
getDoc as getDoc35,
|
|
16962
16646
|
getDocs as getDocs33,
|
|
16963
16647
|
limit as limit18,
|
|
@@ -17009,7 +16693,7 @@ var CategoryService = class extends BaseService {
|
|
|
17009
16693
|
where33("family", "==", family),
|
|
17010
16694
|
where33("isActive", "==", active)
|
|
17011
16695
|
);
|
|
17012
|
-
const snapshot = await
|
|
16696
|
+
const snapshot = await getCountFromServer4(q);
|
|
17013
16697
|
counts[family] = snapshot.data().count;
|
|
17014
16698
|
}
|
|
17015
16699
|
return counts;
|
|
@@ -17150,7 +16834,7 @@ import {
|
|
|
17150
16834
|
collectionGroup as collectionGroup2,
|
|
17151
16835
|
deleteDoc as deleteDoc20,
|
|
17152
16836
|
doc as doc34,
|
|
17153
|
-
getCountFromServer as
|
|
16837
|
+
getCountFromServer as getCountFromServer5,
|
|
17154
16838
|
getDoc as getDoc36,
|
|
17155
16839
|
getDocs as getDocs34,
|
|
17156
16840
|
limit as limit19,
|
|
@@ -17213,7 +16897,7 @@ var SubcategoryService = class extends BaseService {
|
|
|
17213
16897
|
const categoryId = categoryDoc.id;
|
|
17214
16898
|
const subcategoriesRef = this.getSubcategoriesRef(categoryId);
|
|
17215
16899
|
const q = query34(subcategoriesRef, where34("isActive", "==", active));
|
|
17216
|
-
const snapshot = await
|
|
16900
|
+
const snapshot = await getCountFromServer5(q);
|
|
17217
16901
|
counts[categoryId] = snapshot.data().count;
|
|
17218
16902
|
}
|
|
17219
16903
|
return counts;
|
|
@@ -18015,7 +17699,7 @@ import {
|
|
|
18015
17699
|
limit as limit21,
|
|
18016
17700
|
orderBy as orderBy23,
|
|
18017
17701
|
startAfter as startAfter19,
|
|
18018
|
-
getCountFromServer as
|
|
17702
|
+
getCountFromServer as getCountFromServer7
|
|
18019
17703
|
} from "firebase/firestore";
|
|
18020
17704
|
|
|
18021
17705
|
// src/backoffice/types/product.types.ts
|
|
@@ -18094,7 +17778,7 @@ var ProductService = class extends BaseService {
|
|
|
18094
17778
|
constraints.push(where36("technologyId", "==", technologyId));
|
|
18095
17779
|
}
|
|
18096
17780
|
const q = query36(collectionGroup3(this.db, PRODUCTS_COLLECTION), ...constraints);
|
|
18097
|
-
const snapshot = await
|
|
17781
|
+
const snapshot = await getCountFromServer7(q);
|
|
18098
17782
|
return snapshot.data().count;
|
|
18099
17783
|
}
|
|
18100
17784
|
/**
|