@blackcode_sa/metaestetics-api 1.6.16 → 1.6.17
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/index.d.mts +37 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +145 -4
- package/dist/index.mjs +227 -79
- package/package.json +1 -1
- package/src/services/appointment/appointment.service.ts +238 -0
package/dist/index.d.mts
CHANGED
|
@@ -7389,6 +7389,43 @@ declare class AppointmentService extends BaseService {
|
|
|
7389
7389
|
* @returns The updated appointment
|
|
7390
7390
|
*/
|
|
7391
7391
|
updateInternalNotes(appointmentId: string, notes: string | null): Promise<Appointment>;
|
|
7392
|
+
/**
|
|
7393
|
+
* Gets upcoming appointments for a specific patient.
|
|
7394
|
+
* These include appointments with statuses: PENDING, CONFIRMED, CHECKED_IN, IN_PROGRESS
|
|
7395
|
+
*
|
|
7396
|
+
* @param patientId ID of the patient
|
|
7397
|
+
* @param options Optional parameters for filtering and pagination
|
|
7398
|
+
* @returns Found appointments and the last document for pagination
|
|
7399
|
+
*/
|
|
7400
|
+
getUpcomingPatientAppointments(patientId: string, options?: {
|
|
7401
|
+
startDate?: Date;
|
|
7402
|
+
endDate?: Date;
|
|
7403
|
+
limit?: number;
|
|
7404
|
+
startAfter?: DocumentSnapshot;
|
|
7405
|
+
}): Promise<{
|
|
7406
|
+
appointments: Appointment[];
|
|
7407
|
+
lastDoc: DocumentSnapshot | null;
|
|
7408
|
+
}>;
|
|
7409
|
+
/**
|
|
7410
|
+
* Gets past appointments for a specific patient.
|
|
7411
|
+
* These include appointments with statuses: COMPLETED, CANCELED_PATIENT,
|
|
7412
|
+
* CANCELED_PATIENT_RESCHEDULED, CANCELED_CLINIC, NO_SHOW
|
|
7413
|
+
*
|
|
7414
|
+
* @param patientId ID of the patient
|
|
7415
|
+
* @param options Optional parameters for filtering and pagination
|
|
7416
|
+
* @returns Found appointments and the last document for pagination
|
|
7417
|
+
*/
|
|
7418
|
+
getPastPatientAppointments(patientId: string, options?: {
|
|
7419
|
+
startDate?: Date;
|
|
7420
|
+
endDate?: Date;
|
|
7421
|
+
showCanceled?: boolean;
|
|
7422
|
+
showNoShow?: boolean;
|
|
7423
|
+
limit?: number;
|
|
7424
|
+
startAfter?: DocumentSnapshot;
|
|
7425
|
+
}): Promise<{
|
|
7426
|
+
appointments: Appointment[];
|
|
7427
|
+
lastDoc: DocumentSnapshot | null;
|
|
7428
|
+
}>;
|
|
7392
7429
|
}
|
|
7393
7430
|
|
|
7394
7431
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -7389,6 +7389,43 @@ declare class AppointmentService extends BaseService {
|
|
|
7389
7389
|
* @returns The updated appointment
|
|
7390
7390
|
*/
|
|
7391
7391
|
updateInternalNotes(appointmentId: string, notes: string | null): Promise<Appointment>;
|
|
7392
|
+
/**
|
|
7393
|
+
* Gets upcoming appointments for a specific patient.
|
|
7394
|
+
* These include appointments with statuses: PENDING, CONFIRMED, CHECKED_IN, IN_PROGRESS
|
|
7395
|
+
*
|
|
7396
|
+
* @param patientId ID of the patient
|
|
7397
|
+
* @param options Optional parameters for filtering and pagination
|
|
7398
|
+
* @returns Found appointments and the last document for pagination
|
|
7399
|
+
*/
|
|
7400
|
+
getUpcomingPatientAppointments(patientId: string, options?: {
|
|
7401
|
+
startDate?: Date;
|
|
7402
|
+
endDate?: Date;
|
|
7403
|
+
limit?: number;
|
|
7404
|
+
startAfter?: DocumentSnapshot;
|
|
7405
|
+
}): Promise<{
|
|
7406
|
+
appointments: Appointment[];
|
|
7407
|
+
lastDoc: DocumentSnapshot | null;
|
|
7408
|
+
}>;
|
|
7409
|
+
/**
|
|
7410
|
+
* Gets past appointments for a specific patient.
|
|
7411
|
+
* These include appointments with statuses: COMPLETED, CANCELED_PATIENT,
|
|
7412
|
+
* CANCELED_PATIENT_RESCHEDULED, CANCELED_CLINIC, NO_SHOW
|
|
7413
|
+
*
|
|
7414
|
+
* @param patientId ID of the patient
|
|
7415
|
+
* @param options Optional parameters for filtering and pagination
|
|
7416
|
+
* @returns Found appointments and the last document for pagination
|
|
7417
|
+
*/
|
|
7418
|
+
getPastPatientAppointments(patientId: string, options?: {
|
|
7419
|
+
startDate?: Date;
|
|
7420
|
+
endDate?: Date;
|
|
7421
|
+
showCanceled?: boolean;
|
|
7422
|
+
showNoShow?: boolean;
|
|
7423
|
+
limit?: number;
|
|
7424
|
+
startAfter?: DocumentSnapshot;
|
|
7425
|
+
}): Promise<{
|
|
7426
|
+
appointments: Appointment[];
|
|
7427
|
+
lastDoc: DocumentSnapshot | null;
|
|
7428
|
+
}>;
|
|
7392
7429
|
}
|
|
7393
7430
|
|
|
7394
7431
|
/**
|
package/dist/index.js
CHANGED
|
@@ -8108,20 +8108,20 @@ var ProcedureService = class extends BaseService {
|
|
|
8108
8108
|
const proceduresCollection = (0, import_firestore24.collection)(this.db, PROCEDURES_COLLECTION);
|
|
8109
8109
|
let proceduresQuery = (0, import_firestore24.query)(proceduresCollection);
|
|
8110
8110
|
if (pagination && pagination > 0) {
|
|
8111
|
-
const { limit:
|
|
8111
|
+
const { limit: limit13, startAfter: startAfter13 } = await import("firebase/firestore");
|
|
8112
8112
|
if (lastDoc) {
|
|
8113
8113
|
proceduresQuery = (0, import_firestore24.query)(
|
|
8114
8114
|
proceduresCollection,
|
|
8115
8115
|
(0, import_firestore24.orderBy)("name"),
|
|
8116
8116
|
// Use imported orderBy
|
|
8117
|
-
|
|
8118
|
-
|
|
8117
|
+
startAfter13(lastDoc),
|
|
8118
|
+
limit13(pagination)
|
|
8119
8119
|
);
|
|
8120
8120
|
} else {
|
|
8121
8121
|
proceduresQuery = (0, import_firestore24.query)(
|
|
8122
8122
|
proceduresCollection,
|
|
8123
8123
|
(0, import_firestore24.orderBy)("name"),
|
|
8124
|
-
|
|
8124
|
+
limit13(pagination)
|
|
8125
8125
|
);
|
|
8126
8126
|
}
|
|
8127
8127
|
} else {
|
|
@@ -13060,6 +13060,147 @@ var AppointmentService = class extends BaseService {
|
|
|
13060
13060
|
};
|
|
13061
13061
|
return this.updateAppointment(appointmentId, updateData);
|
|
13062
13062
|
}
|
|
13063
|
+
/**
|
|
13064
|
+
* Gets upcoming appointments for a specific patient.
|
|
13065
|
+
* These include appointments with statuses: PENDING, CONFIRMED, CHECKED_IN, IN_PROGRESS
|
|
13066
|
+
*
|
|
13067
|
+
* @param patientId ID of the patient
|
|
13068
|
+
* @param options Optional parameters for filtering and pagination
|
|
13069
|
+
* @returns Found appointments and the last document for pagination
|
|
13070
|
+
*/
|
|
13071
|
+
async getUpcomingPatientAppointments(patientId, options) {
|
|
13072
|
+
try {
|
|
13073
|
+
console.log(
|
|
13074
|
+
`[APPOINTMENT_SERVICE] Getting upcoming appointments for patient: ${patientId}`
|
|
13075
|
+
);
|
|
13076
|
+
const effectiveStartDate = (options == null ? void 0 : options.startDate) || /* @__PURE__ */ new Date();
|
|
13077
|
+
const upcomingStatuses = [
|
|
13078
|
+
"pending" /* PENDING */,
|
|
13079
|
+
"confirmed" /* CONFIRMED */,
|
|
13080
|
+
"checked_in" /* CHECKED_IN */,
|
|
13081
|
+
"in_progress" /* IN_PROGRESS */,
|
|
13082
|
+
"rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */
|
|
13083
|
+
];
|
|
13084
|
+
const constraints = [];
|
|
13085
|
+
constraints.push((0, import_firestore40.where)("patientId", "==", patientId));
|
|
13086
|
+
constraints.push((0, import_firestore40.where)("status", "in", upcomingStatuses));
|
|
13087
|
+
constraints.push(
|
|
13088
|
+
(0, import_firestore40.where)(
|
|
13089
|
+
"appointmentStartTime",
|
|
13090
|
+
">=",
|
|
13091
|
+
import_firestore40.Timestamp.fromDate(effectiveStartDate)
|
|
13092
|
+
)
|
|
13093
|
+
);
|
|
13094
|
+
if (options == null ? void 0 : options.endDate) {
|
|
13095
|
+
constraints.push(
|
|
13096
|
+
(0, import_firestore40.where)(
|
|
13097
|
+
"appointmentStartTime",
|
|
13098
|
+
"<=",
|
|
13099
|
+
import_firestore40.Timestamp.fromDate(options.endDate)
|
|
13100
|
+
)
|
|
13101
|
+
);
|
|
13102
|
+
}
|
|
13103
|
+
constraints.push((0, import_firestore40.orderBy)("appointmentStartTime", "asc"));
|
|
13104
|
+
if (options == null ? void 0 : options.limit) {
|
|
13105
|
+
constraints.push((0, import_firestore40.limit)(options.limit));
|
|
13106
|
+
}
|
|
13107
|
+
if (options == null ? void 0 : options.startAfter) {
|
|
13108
|
+
constraints.push((0, import_firestore40.startAfter)(options.startAfter));
|
|
13109
|
+
}
|
|
13110
|
+
const q = (0, import_firestore40.query)(
|
|
13111
|
+
(0, import_firestore40.collection)(this.db, APPOINTMENTS_COLLECTION),
|
|
13112
|
+
...constraints
|
|
13113
|
+
);
|
|
13114
|
+
const querySnapshot = await (0, import_firestore40.getDocs)(q);
|
|
13115
|
+
const appointments = querySnapshot.docs.map(
|
|
13116
|
+
(doc33) => doc33.data()
|
|
13117
|
+
);
|
|
13118
|
+
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
13119
|
+
console.log(
|
|
13120
|
+
`[APPOINTMENT_SERVICE] Found ${appointments.length} upcoming appointments for patient ${patientId}`
|
|
13121
|
+
);
|
|
13122
|
+
return { appointments, lastDoc };
|
|
13123
|
+
} catch (error) {
|
|
13124
|
+
console.error(
|
|
13125
|
+
`[APPOINTMENT_SERVICE] Error getting upcoming appointments for patient ${patientId}:`,
|
|
13126
|
+
error
|
|
13127
|
+
);
|
|
13128
|
+
throw error;
|
|
13129
|
+
}
|
|
13130
|
+
}
|
|
13131
|
+
/**
|
|
13132
|
+
* Gets past appointments for a specific patient.
|
|
13133
|
+
* These include appointments with statuses: COMPLETED, CANCELED_PATIENT,
|
|
13134
|
+
* CANCELED_PATIENT_RESCHEDULED, CANCELED_CLINIC, NO_SHOW
|
|
13135
|
+
*
|
|
13136
|
+
* @param patientId ID of the patient
|
|
13137
|
+
* @param options Optional parameters for filtering and pagination
|
|
13138
|
+
* @returns Found appointments and the last document for pagination
|
|
13139
|
+
*/
|
|
13140
|
+
async getPastPatientAppointments(patientId, options) {
|
|
13141
|
+
try {
|
|
13142
|
+
console.log(
|
|
13143
|
+
`[APPOINTMENT_SERVICE] Getting past appointments for patient: ${patientId}`
|
|
13144
|
+
);
|
|
13145
|
+
const effectiveEndDate = (options == null ? void 0 : options.endDate) || /* @__PURE__ */ new Date();
|
|
13146
|
+
const pastStatuses = ["completed" /* COMPLETED */];
|
|
13147
|
+
if (options == null ? void 0 : options.showCanceled) {
|
|
13148
|
+
pastStatuses.push(
|
|
13149
|
+
"canceled_patient" /* CANCELED_PATIENT */,
|
|
13150
|
+
"canceled_patient_rescheduled" /* CANCELED_PATIENT_RESCHEDULED */,
|
|
13151
|
+
"canceled_clinic" /* CANCELED_CLINIC */
|
|
13152
|
+
);
|
|
13153
|
+
}
|
|
13154
|
+
if (options == null ? void 0 : options.showNoShow) {
|
|
13155
|
+
pastStatuses.push("no_show" /* NO_SHOW */);
|
|
13156
|
+
}
|
|
13157
|
+
const constraints = [];
|
|
13158
|
+
constraints.push((0, import_firestore40.where)("patientId", "==", patientId));
|
|
13159
|
+
constraints.push((0, import_firestore40.where)("status", "in", pastStatuses));
|
|
13160
|
+
if (options == null ? void 0 : options.startDate) {
|
|
13161
|
+
constraints.push(
|
|
13162
|
+
(0, import_firestore40.where)(
|
|
13163
|
+
"appointmentStartTime",
|
|
13164
|
+
">=",
|
|
13165
|
+
import_firestore40.Timestamp.fromDate(options.startDate)
|
|
13166
|
+
)
|
|
13167
|
+
);
|
|
13168
|
+
}
|
|
13169
|
+
constraints.push(
|
|
13170
|
+
(0, import_firestore40.where)(
|
|
13171
|
+
"appointmentStartTime",
|
|
13172
|
+
"<=",
|
|
13173
|
+
import_firestore40.Timestamp.fromDate(effectiveEndDate)
|
|
13174
|
+
)
|
|
13175
|
+
);
|
|
13176
|
+
constraints.push((0, import_firestore40.orderBy)("appointmentStartTime", "desc"));
|
|
13177
|
+
if (options == null ? void 0 : options.limit) {
|
|
13178
|
+
constraints.push((0, import_firestore40.limit)(options.limit));
|
|
13179
|
+
}
|
|
13180
|
+
if (options == null ? void 0 : options.startAfter) {
|
|
13181
|
+
constraints.push((0, import_firestore40.startAfter)(options.startAfter));
|
|
13182
|
+
}
|
|
13183
|
+
const q = (0, import_firestore40.query)(
|
|
13184
|
+
(0, import_firestore40.collection)(this.db, APPOINTMENTS_COLLECTION),
|
|
13185
|
+
...constraints
|
|
13186
|
+
);
|
|
13187
|
+
const querySnapshot = await (0, import_firestore40.getDocs)(q);
|
|
13188
|
+
const appointments = querySnapshot.docs.map(
|
|
13189
|
+
(doc33) => doc33.data()
|
|
13190
|
+
);
|
|
13191
|
+
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
13192
|
+
console.log(
|
|
13193
|
+
`[APPOINTMENT_SERVICE] Found ${appointments.length} past appointments for patient ${patientId}`
|
|
13194
|
+
);
|
|
13195
|
+
return { appointments, lastDoc };
|
|
13196
|
+
} catch (error) {
|
|
13197
|
+
console.error(
|
|
13198
|
+
`[APPOINTMENT_SERVICE] Error getting past appointments for patient ${patientId}:`,
|
|
13199
|
+
error
|
|
13200
|
+
);
|
|
13201
|
+
throw error;
|
|
13202
|
+
}
|
|
13203
|
+
}
|
|
13063
13204
|
};
|
|
13064
13205
|
|
|
13065
13206
|
// src/services/patient/patientRequirements.service.ts
|
package/dist/index.mjs
CHANGED
|
@@ -8085,20 +8085,20 @@ var ProcedureService = class extends BaseService {
|
|
|
8085
8085
|
const proceduresCollection = collection15(this.db, PROCEDURES_COLLECTION);
|
|
8086
8086
|
let proceduresQuery = query15(proceduresCollection);
|
|
8087
8087
|
if (pagination && pagination > 0) {
|
|
8088
|
-
const { limit:
|
|
8088
|
+
const { limit: limit13, startAfter: startAfter13 } = await import("firebase/firestore");
|
|
8089
8089
|
if (lastDoc) {
|
|
8090
8090
|
proceduresQuery = query15(
|
|
8091
8091
|
proceduresCollection,
|
|
8092
8092
|
orderBy4("name"),
|
|
8093
8093
|
// Use imported orderBy
|
|
8094
|
-
|
|
8095
|
-
|
|
8094
|
+
startAfter13(lastDoc),
|
|
8095
|
+
limit13(pagination)
|
|
8096
8096
|
);
|
|
8097
8097
|
} else {
|
|
8098
8098
|
proceduresQuery = query15(
|
|
8099
8099
|
proceduresCollection,
|
|
8100
8100
|
orderBy4("name"),
|
|
8101
|
-
|
|
8101
|
+
limit13(pagination)
|
|
8102
8102
|
);
|
|
8103
8103
|
}
|
|
8104
8104
|
} else {
|
|
@@ -12249,7 +12249,14 @@ import {
|
|
|
12249
12249
|
Timestamp as Timestamp28,
|
|
12250
12250
|
serverTimestamp as serverTimestamp24,
|
|
12251
12251
|
arrayUnion as arrayUnion8,
|
|
12252
|
-
arrayRemove as arrayRemove7
|
|
12252
|
+
arrayRemove as arrayRemove7,
|
|
12253
|
+
where as where26,
|
|
12254
|
+
orderBy as orderBy13,
|
|
12255
|
+
collection as collection26,
|
|
12256
|
+
query as query26,
|
|
12257
|
+
limit as limit11,
|
|
12258
|
+
startAfter as startAfter11,
|
|
12259
|
+
getDocs as getDocs26
|
|
12253
12260
|
} from "firebase/firestore";
|
|
12254
12261
|
import { getFunctions } from "firebase/functions";
|
|
12255
12262
|
|
|
@@ -13162,20 +13169,161 @@ var AppointmentService = class extends BaseService {
|
|
|
13162
13169
|
};
|
|
13163
13170
|
return this.updateAppointment(appointmentId, updateData);
|
|
13164
13171
|
}
|
|
13172
|
+
/**
|
|
13173
|
+
* Gets upcoming appointments for a specific patient.
|
|
13174
|
+
* These include appointments with statuses: PENDING, CONFIRMED, CHECKED_IN, IN_PROGRESS
|
|
13175
|
+
*
|
|
13176
|
+
* @param patientId ID of the patient
|
|
13177
|
+
* @param options Optional parameters for filtering and pagination
|
|
13178
|
+
* @returns Found appointments and the last document for pagination
|
|
13179
|
+
*/
|
|
13180
|
+
async getUpcomingPatientAppointments(patientId, options) {
|
|
13181
|
+
try {
|
|
13182
|
+
console.log(
|
|
13183
|
+
`[APPOINTMENT_SERVICE] Getting upcoming appointments for patient: ${patientId}`
|
|
13184
|
+
);
|
|
13185
|
+
const effectiveStartDate = (options == null ? void 0 : options.startDate) || /* @__PURE__ */ new Date();
|
|
13186
|
+
const upcomingStatuses = [
|
|
13187
|
+
"pending" /* PENDING */,
|
|
13188
|
+
"confirmed" /* CONFIRMED */,
|
|
13189
|
+
"checked_in" /* CHECKED_IN */,
|
|
13190
|
+
"in_progress" /* IN_PROGRESS */,
|
|
13191
|
+
"rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */
|
|
13192
|
+
];
|
|
13193
|
+
const constraints = [];
|
|
13194
|
+
constraints.push(where26("patientId", "==", patientId));
|
|
13195
|
+
constraints.push(where26("status", "in", upcomingStatuses));
|
|
13196
|
+
constraints.push(
|
|
13197
|
+
where26(
|
|
13198
|
+
"appointmentStartTime",
|
|
13199
|
+
">=",
|
|
13200
|
+
Timestamp28.fromDate(effectiveStartDate)
|
|
13201
|
+
)
|
|
13202
|
+
);
|
|
13203
|
+
if (options == null ? void 0 : options.endDate) {
|
|
13204
|
+
constraints.push(
|
|
13205
|
+
where26(
|
|
13206
|
+
"appointmentStartTime",
|
|
13207
|
+
"<=",
|
|
13208
|
+
Timestamp28.fromDate(options.endDate)
|
|
13209
|
+
)
|
|
13210
|
+
);
|
|
13211
|
+
}
|
|
13212
|
+
constraints.push(orderBy13("appointmentStartTime", "asc"));
|
|
13213
|
+
if (options == null ? void 0 : options.limit) {
|
|
13214
|
+
constraints.push(limit11(options.limit));
|
|
13215
|
+
}
|
|
13216
|
+
if (options == null ? void 0 : options.startAfter) {
|
|
13217
|
+
constraints.push(startAfter11(options.startAfter));
|
|
13218
|
+
}
|
|
13219
|
+
const q = query26(
|
|
13220
|
+
collection26(this.db, APPOINTMENTS_COLLECTION),
|
|
13221
|
+
...constraints
|
|
13222
|
+
);
|
|
13223
|
+
const querySnapshot = await getDocs26(q);
|
|
13224
|
+
const appointments = querySnapshot.docs.map(
|
|
13225
|
+
(doc33) => doc33.data()
|
|
13226
|
+
);
|
|
13227
|
+
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
13228
|
+
console.log(
|
|
13229
|
+
`[APPOINTMENT_SERVICE] Found ${appointments.length} upcoming appointments for patient ${patientId}`
|
|
13230
|
+
);
|
|
13231
|
+
return { appointments, lastDoc };
|
|
13232
|
+
} catch (error) {
|
|
13233
|
+
console.error(
|
|
13234
|
+
`[APPOINTMENT_SERVICE] Error getting upcoming appointments for patient ${patientId}:`,
|
|
13235
|
+
error
|
|
13236
|
+
);
|
|
13237
|
+
throw error;
|
|
13238
|
+
}
|
|
13239
|
+
}
|
|
13240
|
+
/**
|
|
13241
|
+
* Gets past appointments for a specific patient.
|
|
13242
|
+
* These include appointments with statuses: COMPLETED, CANCELED_PATIENT,
|
|
13243
|
+
* CANCELED_PATIENT_RESCHEDULED, CANCELED_CLINIC, NO_SHOW
|
|
13244
|
+
*
|
|
13245
|
+
* @param patientId ID of the patient
|
|
13246
|
+
* @param options Optional parameters for filtering and pagination
|
|
13247
|
+
* @returns Found appointments and the last document for pagination
|
|
13248
|
+
*/
|
|
13249
|
+
async getPastPatientAppointments(patientId, options) {
|
|
13250
|
+
try {
|
|
13251
|
+
console.log(
|
|
13252
|
+
`[APPOINTMENT_SERVICE] Getting past appointments for patient: ${patientId}`
|
|
13253
|
+
);
|
|
13254
|
+
const effectiveEndDate = (options == null ? void 0 : options.endDate) || /* @__PURE__ */ new Date();
|
|
13255
|
+
const pastStatuses = ["completed" /* COMPLETED */];
|
|
13256
|
+
if (options == null ? void 0 : options.showCanceled) {
|
|
13257
|
+
pastStatuses.push(
|
|
13258
|
+
"canceled_patient" /* CANCELED_PATIENT */,
|
|
13259
|
+
"canceled_patient_rescheduled" /* CANCELED_PATIENT_RESCHEDULED */,
|
|
13260
|
+
"canceled_clinic" /* CANCELED_CLINIC */
|
|
13261
|
+
);
|
|
13262
|
+
}
|
|
13263
|
+
if (options == null ? void 0 : options.showNoShow) {
|
|
13264
|
+
pastStatuses.push("no_show" /* NO_SHOW */);
|
|
13265
|
+
}
|
|
13266
|
+
const constraints = [];
|
|
13267
|
+
constraints.push(where26("patientId", "==", patientId));
|
|
13268
|
+
constraints.push(where26("status", "in", pastStatuses));
|
|
13269
|
+
if (options == null ? void 0 : options.startDate) {
|
|
13270
|
+
constraints.push(
|
|
13271
|
+
where26(
|
|
13272
|
+
"appointmentStartTime",
|
|
13273
|
+
">=",
|
|
13274
|
+
Timestamp28.fromDate(options.startDate)
|
|
13275
|
+
)
|
|
13276
|
+
);
|
|
13277
|
+
}
|
|
13278
|
+
constraints.push(
|
|
13279
|
+
where26(
|
|
13280
|
+
"appointmentStartTime",
|
|
13281
|
+
"<=",
|
|
13282
|
+
Timestamp28.fromDate(effectiveEndDate)
|
|
13283
|
+
)
|
|
13284
|
+
);
|
|
13285
|
+
constraints.push(orderBy13("appointmentStartTime", "desc"));
|
|
13286
|
+
if (options == null ? void 0 : options.limit) {
|
|
13287
|
+
constraints.push(limit11(options.limit));
|
|
13288
|
+
}
|
|
13289
|
+
if (options == null ? void 0 : options.startAfter) {
|
|
13290
|
+
constraints.push(startAfter11(options.startAfter));
|
|
13291
|
+
}
|
|
13292
|
+
const q = query26(
|
|
13293
|
+
collection26(this.db, APPOINTMENTS_COLLECTION),
|
|
13294
|
+
...constraints
|
|
13295
|
+
);
|
|
13296
|
+
const querySnapshot = await getDocs26(q);
|
|
13297
|
+
const appointments = querySnapshot.docs.map(
|
|
13298
|
+
(doc33) => doc33.data()
|
|
13299
|
+
);
|
|
13300
|
+
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
13301
|
+
console.log(
|
|
13302
|
+
`[APPOINTMENT_SERVICE] Found ${appointments.length} past appointments for patient ${patientId}`
|
|
13303
|
+
);
|
|
13304
|
+
return { appointments, lastDoc };
|
|
13305
|
+
} catch (error) {
|
|
13306
|
+
console.error(
|
|
13307
|
+
`[APPOINTMENT_SERVICE] Error getting past appointments for patient ${patientId}:`,
|
|
13308
|
+
error
|
|
13309
|
+
);
|
|
13310
|
+
throw error;
|
|
13311
|
+
}
|
|
13312
|
+
}
|
|
13165
13313
|
};
|
|
13166
13314
|
|
|
13167
13315
|
// src/services/patient/patientRequirements.service.ts
|
|
13168
13316
|
import {
|
|
13169
|
-
collection as
|
|
13170
|
-
getDocs as
|
|
13171
|
-
query as
|
|
13172
|
-
where as
|
|
13317
|
+
collection as collection27,
|
|
13318
|
+
getDocs as getDocs27,
|
|
13319
|
+
query as query27,
|
|
13320
|
+
where as where27,
|
|
13173
13321
|
doc as doc27,
|
|
13174
13322
|
updateDoc as updateDoc26,
|
|
13175
13323
|
Timestamp as Timestamp29,
|
|
13176
|
-
orderBy as
|
|
13177
|
-
limit as
|
|
13178
|
-
startAfter as
|
|
13324
|
+
orderBy as orderBy14,
|
|
13325
|
+
limit as limit12,
|
|
13326
|
+
startAfter as startAfter12,
|
|
13179
13327
|
getDoc as getDoc29
|
|
13180
13328
|
} from "firebase/firestore";
|
|
13181
13329
|
|
|
@@ -13207,7 +13355,7 @@ var PatientRequirementsService = class extends BaseService {
|
|
|
13207
13355
|
super(db, auth, app);
|
|
13208
13356
|
}
|
|
13209
13357
|
getPatientRequirementsCollectionRef(patientId) {
|
|
13210
|
-
return
|
|
13358
|
+
return collection27(
|
|
13211
13359
|
this.db,
|
|
13212
13360
|
`patients/${patientId}/${PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME}`
|
|
13213
13361
|
);
|
|
@@ -13245,22 +13393,22 @@ var PatientRequirementsService = class extends BaseService {
|
|
|
13245
13393
|
*/
|
|
13246
13394
|
async getAllPatientRequirementInstances(patientId, filters, pageLimit = 20, lastVisible) {
|
|
13247
13395
|
const collRef = this.getPatientRequirementsCollectionRef(patientId);
|
|
13248
|
-
let q =
|
|
13396
|
+
let q = query27(collRef, orderBy14("createdAt", "desc"));
|
|
13249
13397
|
const queryConstraints = [];
|
|
13250
13398
|
if ((filters == null ? void 0 : filters.appointmentId) && filters.appointmentId !== "all") {
|
|
13251
13399
|
queryConstraints.push(
|
|
13252
|
-
|
|
13400
|
+
where27("appointmentId", "==", filters.appointmentId)
|
|
13253
13401
|
);
|
|
13254
13402
|
}
|
|
13255
13403
|
if ((filters == null ? void 0 : filters.statuses) && filters.statuses.length > 0) {
|
|
13256
|
-
queryConstraints.push(
|
|
13404
|
+
queryConstraints.push(where27("overallStatus", "in", filters.statuses));
|
|
13257
13405
|
}
|
|
13258
13406
|
if (lastVisible) {
|
|
13259
|
-
queryConstraints.push(
|
|
13407
|
+
queryConstraints.push(startAfter12(lastVisible));
|
|
13260
13408
|
}
|
|
13261
|
-
queryConstraints.push(
|
|
13262
|
-
q =
|
|
13263
|
-
const snapshot = await
|
|
13409
|
+
queryConstraints.push(limit12(pageLimit));
|
|
13410
|
+
q = query27(collRef, ...queryConstraints);
|
|
13411
|
+
const snapshot = await getDocs27(q);
|
|
13264
13412
|
let requirements = snapshot.docs.map((docSnap) => {
|
|
13265
13413
|
const data = docSnap.data();
|
|
13266
13414
|
return { id: docSnap.id, ...data };
|
|
@@ -13373,13 +13521,13 @@ var PatientRequirementsService = class extends BaseService {
|
|
|
13373
13521
|
// src/backoffice/services/brand.service.ts
|
|
13374
13522
|
import {
|
|
13375
13523
|
addDoc as addDoc3,
|
|
13376
|
-
collection as
|
|
13524
|
+
collection as collection28,
|
|
13377
13525
|
doc as doc28,
|
|
13378
13526
|
getDoc as getDoc30,
|
|
13379
|
-
getDocs as
|
|
13380
|
-
query as
|
|
13527
|
+
getDocs as getDocs28,
|
|
13528
|
+
query as query28,
|
|
13381
13529
|
updateDoc as updateDoc27,
|
|
13382
|
-
where as
|
|
13530
|
+
where as where28
|
|
13383
13531
|
} from "firebase/firestore";
|
|
13384
13532
|
|
|
13385
13533
|
// src/backoffice/types/brand.types.ts
|
|
@@ -13391,7 +13539,7 @@ var BrandService = class extends BaseService {
|
|
|
13391
13539
|
* Gets reference to brands collection
|
|
13392
13540
|
*/
|
|
13393
13541
|
getBrandsRef() {
|
|
13394
|
-
return
|
|
13542
|
+
return collection28(this.db, BRANDS_COLLECTION);
|
|
13395
13543
|
}
|
|
13396
13544
|
/**
|
|
13397
13545
|
* Creates a new brand
|
|
@@ -13411,8 +13559,8 @@ var BrandService = class extends BaseService {
|
|
|
13411
13559
|
* Gets all active brands
|
|
13412
13560
|
*/
|
|
13413
13561
|
async getAll() {
|
|
13414
|
-
const q =
|
|
13415
|
-
const snapshot = await
|
|
13562
|
+
const q = query28(this.getBrandsRef(), where28("isActive", "==", true));
|
|
13563
|
+
const snapshot = await getDocs28(q);
|
|
13416
13564
|
return snapshot.docs.map(
|
|
13417
13565
|
(doc33) => ({
|
|
13418
13566
|
id: doc33.id,
|
|
@@ -13457,13 +13605,13 @@ var BrandService = class extends BaseService {
|
|
|
13457
13605
|
// src/backoffice/services/category.service.ts
|
|
13458
13606
|
import {
|
|
13459
13607
|
addDoc as addDoc4,
|
|
13460
|
-
collection as
|
|
13608
|
+
collection as collection29,
|
|
13461
13609
|
doc as doc29,
|
|
13462
13610
|
getDoc as getDoc31,
|
|
13463
|
-
getDocs as
|
|
13464
|
-
query as
|
|
13611
|
+
getDocs as getDocs29,
|
|
13612
|
+
query as query29,
|
|
13465
13613
|
updateDoc as updateDoc28,
|
|
13466
|
-
where as
|
|
13614
|
+
where as where29
|
|
13467
13615
|
} from "firebase/firestore";
|
|
13468
13616
|
|
|
13469
13617
|
// src/backoffice/types/category.types.ts
|
|
@@ -13475,7 +13623,7 @@ var CategoryService = class extends BaseService {
|
|
|
13475
13623
|
* Referenca na Firestore kolekciju kategorija
|
|
13476
13624
|
*/
|
|
13477
13625
|
get categoriesRef() {
|
|
13478
|
-
return
|
|
13626
|
+
return collection29(this.db, CATEGORIES_COLLECTION);
|
|
13479
13627
|
}
|
|
13480
13628
|
/**
|
|
13481
13629
|
* Kreira novu kategoriju u sistemu
|
|
@@ -13498,8 +13646,8 @@ var CategoryService = class extends BaseService {
|
|
|
13498
13646
|
* @returns Lista aktivnih kategorija
|
|
13499
13647
|
*/
|
|
13500
13648
|
async getAll() {
|
|
13501
|
-
const q =
|
|
13502
|
-
const snapshot = await
|
|
13649
|
+
const q = query29(this.categoriesRef, where29("isActive", "==", true));
|
|
13650
|
+
const snapshot = await getDocs29(q);
|
|
13503
13651
|
return snapshot.docs.map(
|
|
13504
13652
|
(doc33) => ({
|
|
13505
13653
|
id: doc33.id,
|
|
@@ -13513,12 +13661,12 @@ var CategoryService = class extends BaseService {
|
|
|
13513
13661
|
* @returns Lista kategorija koje pripadaju traženoj familiji
|
|
13514
13662
|
*/
|
|
13515
13663
|
async getAllByFamily(family) {
|
|
13516
|
-
const q =
|
|
13664
|
+
const q = query29(
|
|
13517
13665
|
this.categoriesRef,
|
|
13518
|
-
|
|
13519
|
-
|
|
13666
|
+
where29("family", "==", family),
|
|
13667
|
+
where29("isActive", "==", true)
|
|
13520
13668
|
);
|
|
13521
|
-
const snapshot = await
|
|
13669
|
+
const snapshot = await getDocs29(q);
|
|
13522
13670
|
return snapshot.docs.map(
|
|
13523
13671
|
(doc33) => ({
|
|
13524
13672
|
id: doc33.id,
|
|
@@ -13567,13 +13715,13 @@ var CategoryService = class extends BaseService {
|
|
|
13567
13715
|
// src/backoffice/services/subcategory.service.ts
|
|
13568
13716
|
import {
|
|
13569
13717
|
addDoc as addDoc5,
|
|
13570
|
-
collection as
|
|
13718
|
+
collection as collection30,
|
|
13571
13719
|
doc as doc30,
|
|
13572
13720
|
getDoc as getDoc32,
|
|
13573
|
-
getDocs as
|
|
13574
|
-
query as
|
|
13721
|
+
getDocs as getDocs30,
|
|
13722
|
+
query as query30,
|
|
13575
13723
|
updateDoc as updateDoc29,
|
|
13576
|
-
where as
|
|
13724
|
+
where as where30
|
|
13577
13725
|
} from "firebase/firestore";
|
|
13578
13726
|
|
|
13579
13727
|
// src/backoffice/types/subcategory.types.ts
|
|
@@ -13586,7 +13734,7 @@ var SubcategoryService = class extends BaseService {
|
|
|
13586
13734
|
* @param categoryId - ID roditeljske kategorije
|
|
13587
13735
|
*/
|
|
13588
13736
|
getSubcategoriesRef(categoryId) {
|
|
13589
|
-
return
|
|
13737
|
+
return collection30(
|
|
13590
13738
|
this.db,
|
|
13591
13739
|
CATEGORIES_COLLECTION,
|
|
13592
13740
|
categoryId,
|
|
@@ -13620,11 +13768,11 @@ var SubcategoryService = class extends BaseService {
|
|
|
13620
13768
|
* @returns Lista aktivnih podkategorija
|
|
13621
13769
|
*/
|
|
13622
13770
|
async getAllByCategoryId(categoryId) {
|
|
13623
|
-
const q =
|
|
13771
|
+
const q = query30(
|
|
13624
13772
|
this.getSubcategoriesRef(categoryId),
|
|
13625
|
-
|
|
13773
|
+
where30("isActive", "==", true)
|
|
13626
13774
|
);
|
|
13627
|
-
const snapshot = await
|
|
13775
|
+
const snapshot = await getDocs30(q);
|
|
13628
13776
|
return snapshot.docs.map(
|
|
13629
13777
|
(doc33) => ({
|
|
13630
13778
|
id: doc33.id,
|
|
@@ -13676,13 +13824,13 @@ var SubcategoryService = class extends BaseService {
|
|
|
13676
13824
|
// src/backoffice/services/technology.service.ts
|
|
13677
13825
|
import {
|
|
13678
13826
|
addDoc as addDoc6,
|
|
13679
|
-
collection as
|
|
13827
|
+
collection as collection31,
|
|
13680
13828
|
doc as doc31,
|
|
13681
13829
|
getDoc as getDoc33,
|
|
13682
|
-
getDocs as
|
|
13683
|
-
query as
|
|
13830
|
+
getDocs as getDocs31,
|
|
13831
|
+
query as query31,
|
|
13684
13832
|
updateDoc as updateDoc30,
|
|
13685
|
-
where as
|
|
13833
|
+
where as where31,
|
|
13686
13834
|
arrayUnion as arrayUnion9,
|
|
13687
13835
|
arrayRemove as arrayRemove8
|
|
13688
13836
|
} from "firebase/firestore";
|
|
@@ -13695,7 +13843,7 @@ var TechnologyService = class extends BaseService {
|
|
|
13695
13843
|
* Vraća referencu na Firestore kolekciju tehnologija
|
|
13696
13844
|
*/
|
|
13697
13845
|
getTechnologiesRef() {
|
|
13698
|
-
return
|
|
13846
|
+
return collection31(this.db, TECHNOLOGIES_COLLECTION);
|
|
13699
13847
|
}
|
|
13700
13848
|
/**
|
|
13701
13849
|
* Kreira novu tehnologiju
|
|
@@ -13726,8 +13874,8 @@ var TechnologyService = class extends BaseService {
|
|
|
13726
13874
|
* @returns Lista aktivnih tehnologija
|
|
13727
13875
|
*/
|
|
13728
13876
|
async getAll() {
|
|
13729
|
-
const q =
|
|
13730
|
-
const snapshot = await
|
|
13877
|
+
const q = query31(this.getTechnologiesRef(), where31("isActive", "==", true));
|
|
13878
|
+
const snapshot = await getDocs31(q);
|
|
13731
13879
|
return snapshot.docs.map(
|
|
13732
13880
|
(doc33) => ({
|
|
13733
13881
|
id: doc33.id,
|
|
@@ -13741,12 +13889,12 @@ var TechnologyService = class extends BaseService {
|
|
|
13741
13889
|
* @returns Lista aktivnih tehnologija
|
|
13742
13890
|
*/
|
|
13743
13891
|
async getAllByFamily(family) {
|
|
13744
|
-
const q =
|
|
13892
|
+
const q = query31(
|
|
13745
13893
|
this.getTechnologiesRef(),
|
|
13746
|
-
|
|
13747
|
-
|
|
13894
|
+
where31("isActive", "==", true),
|
|
13895
|
+
where31("family", "==", family)
|
|
13748
13896
|
);
|
|
13749
|
-
const snapshot = await
|
|
13897
|
+
const snapshot = await getDocs31(q);
|
|
13750
13898
|
return snapshot.docs.map(
|
|
13751
13899
|
(doc33) => ({
|
|
13752
13900
|
id: doc33.id,
|
|
@@ -13760,12 +13908,12 @@ var TechnologyService = class extends BaseService {
|
|
|
13760
13908
|
* @returns Lista aktivnih tehnologija
|
|
13761
13909
|
*/
|
|
13762
13910
|
async getAllByCategoryId(categoryId) {
|
|
13763
|
-
const q =
|
|
13911
|
+
const q = query31(
|
|
13764
13912
|
this.getTechnologiesRef(),
|
|
13765
|
-
|
|
13766
|
-
|
|
13913
|
+
where31("isActive", "==", true),
|
|
13914
|
+
where31("categoryId", "==", categoryId)
|
|
13767
13915
|
);
|
|
13768
|
-
const snapshot = await
|
|
13916
|
+
const snapshot = await getDocs31(q);
|
|
13769
13917
|
return snapshot.docs.map(
|
|
13770
13918
|
(doc33) => ({
|
|
13771
13919
|
id: doc33.id,
|
|
@@ -13779,12 +13927,12 @@ var TechnologyService = class extends BaseService {
|
|
|
13779
13927
|
* @returns Lista aktivnih tehnologija
|
|
13780
13928
|
*/
|
|
13781
13929
|
async getAllBySubcategoryId(subcategoryId) {
|
|
13782
|
-
const q =
|
|
13930
|
+
const q = query31(
|
|
13783
13931
|
this.getTechnologiesRef(),
|
|
13784
|
-
|
|
13785
|
-
|
|
13932
|
+
where31("isActive", "==", true),
|
|
13933
|
+
where31("subcategoryId", "==", subcategoryId)
|
|
13786
13934
|
);
|
|
13787
|
-
const snapshot = await
|
|
13935
|
+
const snapshot = await getDocs31(q);
|
|
13788
13936
|
return snapshot.docs.map(
|
|
13789
13937
|
(doc33) => ({
|
|
13790
13938
|
id: doc33.id,
|
|
@@ -14106,13 +14254,13 @@ var TechnologyService = class extends BaseService {
|
|
|
14106
14254
|
// src/backoffice/services/product.service.ts
|
|
14107
14255
|
import {
|
|
14108
14256
|
addDoc as addDoc7,
|
|
14109
|
-
collection as
|
|
14257
|
+
collection as collection32,
|
|
14110
14258
|
doc as doc32,
|
|
14111
14259
|
getDoc as getDoc34,
|
|
14112
|
-
getDocs as
|
|
14113
|
-
query as
|
|
14260
|
+
getDocs as getDocs32,
|
|
14261
|
+
query as query32,
|
|
14114
14262
|
updateDoc as updateDoc31,
|
|
14115
|
-
where as
|
|
14263
|
+
where as where32
|
|
14116
14264
|
} from "firebase/firestore";
|
|
14117
14265
|
|
|
14118
14266
|
// src/backoffice/types/product.types.ts
|
|
@@ -14126,7 +14274,7 @@ var ProductService = class extends BaseService {
|
|
|
14126
14274
|
* @returns Firestore collection reference
|
|
14127
14275
|
*/
|
|
14128
14276
|
getProductsRef(technologyId) {
|
|
14129
|
-
return
|
|
14277
|
+
return collection32(
|
|
14130
14278
|
this.db,
|
|
14131
14279
|
TECHNOLOGIES_COLLECTION,
|
|
14132
14280
|
technologyId,
|
|
@@ -14156,11 +14304,11 @@ var ProductService = class extends BaseService {
|
|
|
14156
14304
|
* Gets all products for a technology
|
|
14157
14305
|
*/
|
|
14158
14306
|
async getAllByTechnology(technologyId) {
|
|
14159
|
-
const q =
|
|
14307
|
+
const q = query32(
|
|
14160
14308
|
this.getProductsRef(technologyId),
|
|
14161
|
-
|
|
14309
|
+
where32("isActive", "==", true)
|
|
14162
14310
|
);
|
|
14163
|
-
const snapshot = await
|
|
14311
|
+
const snapshot = await getDocs32(q);
|
|
14164
14312
|
return snapshot.docs.map(
|
|
14165
14313
|
(doc33) => ({
|
|
14166
14314
|
id: doc33.id,
|
|
@@ -14172,16 +14320,16 @@ var ProductService = class extends BaseService {
|
|
|
14172
14320
|
* Gets all products for a brand by filtering through all technologies
|
|
14173
14321
|
*/
|
|
14174
14322
|
async getAllByBrand(brandId) {
|
|
14175
|
-
const allTechnologiesRef =
|
|
14176
|
-
const technologiesSnapshot = await
|
|
14323
|
+
const allTechnologiesRef = collection32(this.db, TECHNOLOGIES_COLLECTION);
|
|
14324
|
+
const technologiesSnapshot = await getDocs32(allTechnologiesRef);
|
|
14177
14325
|
const products = [];
|
|
14178
14326
|
for (const techDoc of technologiesSnapshot.docs) {
|
|
14179
|
-
const q =
|
|
14327
|
+
const q = query32(
|
|
14180
14328
|
this.getProductsRef(techDoc.id),
|
|
14181
|
-
|
|
14182
|
-
|
|
14329
|
+
where32("brandId", "==", brandId),
|
|
14330
|
+
where32("isActive", "==", true)
|
|
14183
14331
|
);
|
|
14184
|
-
const snapshot = await
|
|
14332
|
+
const snapshot = await getDocs32(q);
|
|
14185
14333
|
products.push(
|
|
14186
14334
|
...snapshot.docs.map(
|
|
14187
14335
|
(doc33) => ({
|
package/package.json
CHANGED
|
@@ -5,6 +5,14 @@ import {
|
|
|
5
5
|
serverTimestamp,
|
|
6
6
|
arrayUnion,
|
|
7
7
|
arrayRemove,
|
|
8
|
+
QueryConstraint,
|
|
9
|
+
where,
|
|
10
|
+
orderBy,
|
|
11
|
+
collection,
|
|
12
|
+
query,
|
|
13
|
+
limit,
|
|
14
|
+
startAfter,
|
|
15
|
+
getDocs,
|
|
8
16
|
} from "firebase/firestore";
|
|
9
17
|
import { Auth } from "firebase/auth";
|
|
10
18
|
import { FirebaseApp } from "firebase/app";
|
|
@@ -21,6 +29,7 @@ import {
|
|
|
21
29
|
PatientReviewInfo,
|
|
22
30
|
LinkedFormInfo,
|
|
23
31
|
type CreateAppointmentHttpData,
|
|
32
|
+
APPOINTMENTS_COLLECTION,
|
|
24
33
|
} from "../../types/appointment";
|
|
25
34
|
import {
|
|
26
35
|
createAppointmentSchema,
|
|
@@ -1002,4 +1011,233 @@ export class AppointmentService extends BaseService {
|
|
|
1002
1011
|
|
|
1003
1012
|
return this.updateAppointment(appointmentId, updateData);
|
|
1004
1013
|
}
|
|
1014
|
+
|
|
1015
|
+
/**
|
|
1016
|
+
* Gets upcoming appointments for a specific patient.
|
|
1017
|
+
* These include appointments with statuses: PENDING, CONFIRMED, CHECKED_IN, IN_PROGRESS
|
|
1018
|
+
*
|
|
1019
|
+
* @param patientId ID of the patient
|
|
1020
|
+
* @param options Optional parameters for filtering and pagination
|
|
1021
|
+
* @returns Found appointments and the last document for pagination
|
|
1022
|
+
*/
|
|
1023
|
+
async getUpcomingPatientAppointments(
|
|
1024
|
+
patientId: string,
|
|
1025
|
+
options?: {
|
|
1026
|
+
startDate?: Date; // Optional starting date (defaults to now)
|
|
1027
|
+
endDate?: Date;
|
|
1028
|
+
limit?: number;
|
|
1029
|
+
startAfter?: DocumentSnapshot;
|
|
1030
|
+
}
|
|
1031
|
+
): Promise<{
|
|
1032
|
+
appointments: Appointment[];
|
|
1033
|
+
lastDoc: DocumentSnapshot | null;
|
|
1034
|
+
}> {
|
|
1035
|
+
try {
|
|
1036
|
+
console.log(
|
|
1037
|
+
`[APPOINTMENT_SERVICE] Getting upcoming appointments for patient: ${patientId}`
|
|
1038
|
+
);
|
|
1039
|
+
|
|
1040
|
+
// Default to current date/time if no startDate provided
|
|
1041
|
+
const effectiveStartDate = options?.startDate || new Date();
|
|
1042
|
+
|
|
1043
|
+
// Define the statuses considered as "upcoming"
|
|
1044
|
+
const upcomingStatuses = [
|
|
1045
|
+
AppointmentStatus.PENDING,
|
|
1046
|
+
AppointmentStatus.CONFIRMED,
|
|
1047
|
+
AppointmentStatus.CHECKED_IN,
|
|
1048
|
+
AppointmentStatus.IN_PROGRESS,
|
|
1049
|
+
AppointmentStatus.RESCHEDULED_BY_CLINIC,
|
|
1050
|
+
];
|
|
1051
|
+
|
|
1052
|
+
// Build query constraints
|
|
1053
|
+
const constraints: QueryConstraint[] = [];
|
|
1054
|
+
|
|
1055
|
+
// Patient ID filter
|
|
1056
|
+
constraints.push(where("patientId", "==", patientId));
|
|
1057
|
+
|
|
1058
|
+
// Status filter - multiple statuses
|
|
1059
|
+
constraints.push(where("status", "in", upcomingStatuses));
|
|
1060
|
+
|
|
1061
|
+
// Date range filters
|
|
1062
|
+
constraints.push(
|
|
1063
|
+
where(
|
|
1064
|
+
"appointmentStartTime",
|
|
1065
|
+
">=",
|
|
1066
|
+
Timestamp.fromDate(effectiveStartDate)
|
|
1067
|
+
)
|
|
1068
|
+
);
|
|
1069
|
+
|
|
1070
|
+
if (options?.endDate) {
|
|
1071
|
+
constraints.push(
|
|
1072
|
+
where(
|
|
1073
|
+
"appointmentStartTime",
|
|
1074
|
+
"<=",
|
|
1075
|
+
Timestamp.fromDate(options.endDate)
|
|
1076
|
+
)
|
|
1077
|
+
);
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
// Order by appointment start time (ascending for upcoming - closest first)
|
|
1081
|
+
constraints.push(orderBy("appointmentStartTime", "asc"));
|
|
1082
|
+
|
|
1083
|
+
// Add pagination if specified
|
|
1084
|
+
if (options?.limit) {
|
|
1085
|
+
constraints.push(limit(options.limit));
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
if (options?.startAfter) {
|
|
1089
|
+
constraints.push(startAfter(options.startAfter));
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
// Execute query
|
|
1093
|
+
const q = query(
|
|
1094
|
+
collection(this.db, APPOINTMENTS_COLLECTION),
|
|
1095
|
+
...constraints
|
|
1096
|
+
);
|
|
1097
|
+
const querySnapshot = await getDocs(q);
|
|
1098
|
+
|
|
1099
|
+
// Extract results
|
|
1100
|
+
const appointments = querySnapshot.docs.map(
|
|
1101
|
+
(doc) => doc.data() as Appointment
|
|
1102
|
+
);
|
|
1103
|
+
|
|
1104
|
+
// Get last document for pagination
|
|
1105
|
+
const lastDoc =
|
|
1106
|
+
querySnapshot.docs.length > 0
|
|
1107
|
+
? querySnapshot.docs[querySnapshot.docs.length - 1]
|
|
1108
|
+
: null;
|
|
1109
|
+
|
|
1110
|
+
console.log(
|
|
1111
|
+
`[APPOINTMENT_SERVICE] Found ${appointments.length} upcoming appointments for patient ${patientId}`
|
|
1112
|
+
);
|
|
1113
|
+
|
|
1114
|
+
return { appointments, lastDoc };
|
|
1115
|
+
} catch (error) {
|
|
1116
|
+
console.error(
|
|
1117
|
+
`[APPOINTMENT_SERVICE] Error getting upcoming appointments for patient ${patientId}:`,
|
|
1118
|
+
error
|
|
1119
|
+
);
|
|
1120
|
+
throw error;
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
/**
|
|
1125
|
+
* Gets past appointments for a specific patient.
|
|
1126
|
+
* These include appointments with statuses: COMPLETED, CANCELED_PATIENT,
|
|
1127
|
+
* CANCELED_PATIENT_RESCHEDULED, CANCELED_CLINIC, NO_SHOW
|
|
1128
|
+
*
|
|
1129
|
+
* @param patientId ID of the patient
|
|
1130
|
+
* @param options Optional parameters for filtering and pagination
|
|
1131
|
+
* @returns Found appointments and the last document for pagination
|
|
1132
|
+
*/
|
|
1133
|
+
async getPastPatientAppointments(
|
|
1134
|
+
patientId: string,
|
|
1135
|
+
options?: {
|
|
1136
|
+
startDate?: Date;
|
|
1137
|
+
endDate?: Date; // Optional end date (defaults to now)
|
|
1138
|
+
showCanceled?: boolean; // Whether to include canceled appointments
|
|
1139
|
+
showNoShow?: boolean; // Whether to include no-show appointments
|
|
1140
|
+
limit?: number;
|
|
1141
|
+
startAfter?: DocumentSnapshot;
|
|
1142
|
+
}
|
|
1143
|
+
): Promise<{
|
|
1144
|
+
appointments: Appointment[];
|
|
1145
|
+
lastDoc: DocumentSnapshot | null;
|
|
1146
|
+
}> {
|
|
1147
|
+
try {
|
|
1148
|
+
console.log(
|
|
1149
|
+
`[APPOINTMENT_SERVICE] Getting past appointments for patient: ${patientId}`
|
|
1150
|
+
);
|
|
1151
|
+
|
|
1152
|
+
// Default to current date/time if no endDate provided
|
|
1153
|
+
const effectiveEndDate = options?.endDate || new Date();
|
|
1154
|
+
|
|
1155
|
+
// Define the base status for past appointments
|
|
1156
|
+
const pastStatuses: AppointmentStatus[] = [AppointmentStatus.COMPLETED];
|
|
1157
|
+
|
|
1158
|
+
// Add canceled statuses if requested
|
|
1159
|
+
if (options?.showCanceled) {
|
|
1160
|
+
pastStatuses.push(
|
|
1161
|
+
AppointmentStatus.CANCELED_PATIENT,
|
|
1162
|
+
AppointmentStatus.CANCELED_PATIENT_RESCHEDULED,
|
|
1163
|
+
AppointmentStatus.CANCELED_CLINIC
|
|
1164
|
+
);
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
// Add no-show status if requested
|
|
1168
|
+
if (options?.showNoShow) {
|
|
1169
|
+
pastStatuses.push(AppointmentStatus.NO_SHOW);
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
// Build query constraints
|
|
1173
|
+
const constraints: QueryConstraint[] = [];
|
|
1174
|
+
|
|
1175
|
+
// Patient ID filter
|
|
1176
|
+
constraints.push(where("patientId", "==", patientId));
|
|
1177
|
+
|
|
1178
|
+
// Status filter - multiple statuses
|
|
1179
|
+
constraints.push(where("status", "in", pastStatuses));
|
|
1180
|
+
|
|
1181
|
+
// Date range filters
|
|
1182
|
+
if (options?.startDate) {
|
|
1183
|
+
constraints.push(
|
|
1184
|
+
where(
|
|
1185
|
+
"appointmentStartTime",
|
|
1186
|
+
">=",
|
|
1187
|
+
Timestamp.fromDate(options.startDate)
|
|
1188
|
+
)
|
|
1189
|
+
);
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
constraints.push(
|
|
1193
|
+
where(
|
|
1194
|
+
"appointmentStartTime",
|
|
1195
|
+
"<=",
|
|
1196
|
+
Timestamp.fromDate(effectiveEndDate)
|
|
1197
|
+
)
|
|
1198
|
+
);
|
|
1199
|
+
|
|
1200
|
+
// Order by appointment start time (descending for past - most recent first)
|
|
1201
|
+
constraints.push(orderBy("appointmentStartTime", "desc"));
|
|
1202
|
+
|
|
1203
|
+
// Add pagination if specified
|
|
1204
|
+
if (options?.limit) {
|
|
1205
|
+
constraints.push(limit(options.limit));
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
if (options?.startAfter) {
|
|
1209
|
+
constraints.push(startAfter(options.startAfter));
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
// Execute query
|
|
1213
|
+
const q = query(
|
|
1214
|
+
collection(this.db, APPOINTMENTS_COLLECTION),
|
|
1215
|
+
...constraints
|
|
1216
|
+
);
|
|
1217
|
+
const querySnapshot = await getDocs(q);
|
|
1218
|
+
|
|
1219
|
+
// Extract results
|
|
1220
|
+
const appointments = querySnapshot.docs.map(
|
|
1221
|
+
(doc) => doc.data() as Appointment
|
|
1222
|
+
);
|
|
1223
|
+
|
|
1224
|
+
// Get last document for pagination
|
|
1225
|
+
const lastDoc =
|
|
1226
|
+
querySnapshot.docs.length > 0
|
|
1227
|
+
? querySnapshot.docs[querySnapshot.docs.length - 1]
|
|
1228
|
+
: null;
|
|
1229
|
+
|
|
1230
|
+
console.log(
|
|
1231
|
+
`[APPOINTMENT_SERVICE] Found ${appointments.length} past appointments for patient ${patientId}`
|
|
1232
|
+
);
|
|
1233
|
+
|
|
1234
|
+
return { appointments, lastDoc };
|
|
1235
|
+
} catch (error) {
|
|
1236
|
+
console.error(
|
|
1237
|
+
`[APPOINTMENT_SERVICE] Error getting past appointments for patient ${patientId}:`,
|
|
1238
|
+
error
|
|
1239
|
+
);
|
|
1240
|
+
throw error;
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1005
1243
|
}
|