@blackcode_sa/metaestetics-api 1.6.3 → 1.6.4
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 +228 -25
- package/dist/admin/index.d.ts +228 -25
- package/dist/admin/index.js +35867 -2493
- package/dist/admin/index.mjs +35856 -2464
- package/dist/backoffice/index.d.mts +252 -1
- package/dist/backoffice/index.d.ts +252 -1
- package/dist/backoffice/index.js +86 -12
- package/dist/backoffice/index.mjs +86 -13
- package/dist/index.d.mts +1400 -554
- package/dist/index.d.ts +1400 -554
- package/dist/index.js +1325 -683
- package/dist/index.mjs +1358 -710
- package/package.json +1 -1
- package/src/admin/index.ts +15 -1
- package/src/admin/notifications/notifications.admin.ts +1 -1
- package/src/admin/requirements/README.md +128 -0
- package/src/admin/requirements/patient-requirements.admin.service.ts +482 -0
- package/src/index.ts +16 -1
- package/src/services/appointment/appointment.service.ts +315 -86
- package/src/services/clinic/clinic-admin.service.ts +3 -0
- package/src/services/clinic/clinic-group.service.ts +8 -0
- package/src/services/documentation-templates/documentation-template.service.ts +24 -16
- package/src/services/documentation-templates/filled-document.service.ts +253 -136
- package/src/services/patient/patientRequirements.service.ts +285 -0
- package/src/types/appointment/index.ts +134 -10
- package/src/types/documentation-templates/index.ts +34 -2
- package/src/types/notifications/README.md +77 -0
- package/src/types/notifications/index.ts +154 -27
- package/src/types/patient/patient-requirements.ts +81 -0
- package/src/validations/appointment.schema.ts +300 -62
- package/src/validations/documentation-templates/template.schema.ts +55 -0
- package/src/validations/documentation-templates.schema.ts +9 -14
- package/src/validations/notification.schema.ts +3 -3
- package/src/validations/patient/patient-requirements.schema.ts +75 -0
package/dist/index.js
CHANGED
|
@@ -81,9 +81,13 @@ __export(index_exports, {
|
|
|
81
81
|
PATIENT_LOCATION_INFO_COLLECTION: () => PATIENT_LOCATION_INFO_COLLECTION,
|
|
82
82
|
PATIENT_MEDICAL_HISTORY_COLLECTION: () => PATIENT_MEDICAL_HISTORY_COLLECTION,
|
|
83
83
|
PATIENT_MEDICAL_INFO_COLLECTION: () => PATIENT_MEDICAL_INFO_COLLECTION,
|
|
84
|
+
PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME: () => PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME,
|
|
84
85
|
PATIENT_SENSITIVE_INFO_COLLECTION: () => PATIENT_SENSITIVE_INFO_COLLECTION,
|
|
85
86
|
PRACTITIONERS_COLLECTION: () => PRACTITIONERS_COLLECTION,
|
|
86
87
|
PROCEDURES_COLLECTION: () => PROCEDURES_COLLECTION,
|
|
88
|
+
PatientInstructionStatus: () => PatientInstructionStatus,
|
|
89
|
+
PatientRequirementOverallStatus: () => PatientRequirementOverallStatus,
|
|
90
|
+
PatientRequirementsService: () => PatientRequirementsService,
|
|
87
91
|
PatientService: () => PatientService,
|
|
88
92
|
PaymentStatus: () => PaymentStatus,
|
|
89
93
|
PracticeType: () => PracticeType,
|
|
@@ -148,6 +152,7 @@ __export(index_exports, {
|
|
|
148
152
|
createDefaultClinicGroupSchema: () => createDefaultClinicGroupSchema,
|
|
149
153
|
createDocumentTemplateSchema: () => createDocumentTemplateSchema,
|
|
150
154
|
createDraftPractitionerSchema: () => createDraftPractitionerSchema,
|
|
155
|
+
createFilledDocumentDataSchema: () => createFilledDocumentDataSchema,
|
|
151
156
|
createPatientLocationInfoSchema: () => createPatientLocationInfoSchema,
|
|
152
157
|
createPatientMedicalInfoSchema: () => createPatientMedicalInfoSchema,
|
|
153
158
|
createPatientProfileSchema: () => createPatientProfileSchema,
|
|
@@ -163,6 +168,8 @@ __export(index_exports, {
|
|
|
163
168
|
documentTemplateSchema: () => documentTemplateSchema,
|
|
164
169
|
emailSchema: () => emailSchema,
|
|
165
170
|
emergencyContactSchema: () => emergencyContactSchema,
|
|
171
|
+
filledDocumentSchema: () => filledDocumentSchema,
|
|
172
|
+
filledDocumentStatusSchema: () => filledDocumentStatusSchema,
|
|
166
173
|
gamificationSchema: () => gamificationSchema,
|
|
167
174
|
getFirebaseApp: () => getFirebaseApp,
|
|
168
175
|
getFirebaseAuth: () => getFirebaseAuth,
|
|
@@ -212,6 +219,7 @@ __export(index_exports, {
|
|
|
212
219
|
updateClinicSchema: () => updateClinicSchema,
|
|
213
220
|
updateContraindicationSchema: () => updateContraindicationSchema,
|
|
214
221
|
updateDocumentTemplateSchema: () => updateDocumentTemplateSchema,
|
|
222
|
+
updateFilledDocumentDataSchema: () => updateFilledDocumentDataSchema,
|
|
215
223
|
updateMedicationSchema: () => updateMedicationSchema,
|
|
216
224
|
updatePatientMedicalInfoSchema: () => updatePatientMedicalInfoSchema,
|
|
217
225
|
updateVitalStatsSchema: () => updateVitalStatsSchema,
|
|
@@ -224,19 +232,20 @@ __export(index_exports, {
|
|
|
224
232
|
module.exports = __toCommonJS(index_exports);
|
|
225
233
|
|
|
226
234
|
// src/validations/appointment.schema.ts
|
|
227
|
-
var
|
|
235
|
+
var import_zod2 = require("zod");
|
|
228
236
|
|
|
229
237
|
// src/types/appointment/index.ts
|
|
230
238
|
var AppointmentStatus = /* @__PURE__ */ ((AppointmentStatus2) => {
|
|
231
|
-
AppointmentStatus2["
|
|
239
|
+
AppointmentStatus2["PENDING"] = "pending";
|
|
232
240
|
AppointmentStatus2["CONFIRMED"] = "confirmed";
|
|
233
241
|
AppointmentStatus2["CHECKED_IN"] = "checked_in";
|
|
234
242
|
AppointmentStatus2["IN_PROGRESS"] = "in_progress";
|
|
235
243
|
AppointmentStatus2["COMPLETED"] = "completed";
|
|
236
244
|
AppointmentStatus2["CANCELED_PATIENT"] = "canceled_patient";
|
|
245
|
+
AppointmentStatus2["CANCELED_PATIENT_RESCHEDULED"] = "canceled_patient_rescheduled";
|
|
237
246
|
AppointmentStatus2["CANCELED_CLINIC"] = "canceled_clinic";
|
|
238
247
|
AppointmentStatus2["NO_SHOW"] = "no_show";
|
|
239
|
-
AppointmentStatus2["
|
|
248
|
+
AppointmentStatus2["RESCHEDULED_BY_CLINIC"] = "rescheduled_by_clinic";
|
|
240
249
|
return AppointmentStatus2;
|
|
241
250
|
})(AppointmentStatus || {});
|
|
242
251
|
var PaymentStatus = /* @__PURE__ */ ((PaymentStatus3) => {
|
|
@@ -247,82 +256,444 @@ var PaymentStatus = /* @__PURE__ */ ((PaymentStatus3) => {
|
|
|
247
256
|
PaymentStatus3["NOT_APPLICABLE"] = "not_applicable";
|
|
248
257
|
return PaymentStatus3;
|
|
249
258
|
})(PaymentStatus || {});
|
|
259
|
+
var MediaType = /* @__PURE__ */ ((MediaType2) => {
|
|
260
|
+
MediaType2["BEFORE_PHOTO"] = "before_photo";
|
|
261
|
+
MediaType2["AFTER_PHOTO"] = "after_photo";
|
|
262
|
+
MediaType2["CONSENT_SCAN"] = "consent_scan";
|
|
263
|
+
MediaType2["OTHER_DOCUMENT"] = "other_document";
|
|
264
|
+
return MediaType2;
|
|
265
|
+
})(MediaType || {});
|
|
250
266
|
var APPOINTMENTS_COLLECTION = "appointments";
|
|
251
267
|
|
|
268
|
+
// src/validations/documentation-templates/template.schema.ts
|
|
269
|
+
var import_zod = require("zod");
|
|
270
|
+
|
|
271
|
+
// src/types/documentation-templates/index.ts
|
|
272
|
+
var DOCUMENTATION_TEMPLATES_COLLECTION = "documentation-templates";
|
|
273
|
+
var FILLED_DOCUMENTS_COLLECTION = "filled-documents";
|
|
274
|
+
var USER_FORMS_SUBCOLLECTION = "user-forms";
|
|
275
|
+
var DOCTOR_FORMS_SUBCOLLECTION = "doctor-forms";
|
|
276
|
+
var DocumentElementType = /* @__PURE__ */ ((DocumentElementType2) => {
|
|
277
|
+
DocumentElementType2["HEADING"] = "heading";
|
|
278
|
+
DocumentElementType2["PARAGRAPH"] = "paragraph";
|
|
279
|
+
DocumentElementType2["LIST"] = "list";
|
|
280
|
+
DocumentElementType2["DYNAMIC_TEXT"] = "dynamic_text";
|
|
281
|
+
DocumentElementType2["BINARY_CHOICE"] = "binary_choice";
|
|
282
|
+
DocumentElementType2["MULTIPLE_CHOICE"] = "multiple_choice";
|
|
283
|
+
DocumentElementType2["SINGLE_CHOICE"] = "single_choice";
|
|
284
|
+
DocumentElementType2["RATING_SCALE"] = "rating_scale";
|
|
285
|
+
DocumentElementType2["TEXT_INPUT"] = "text_input";
|
|
286
|
+
DocumentElementType2["DATE_PICKER"] = "date_picker";
|
|
287
|
+
DocumentElementType2["SIGNATURE"] = "signature";
|
|
288
|
+
DocumentElementType2["DITIGAL_SIGNATURE"] = "digital_signature";
|
|
289
|
+
DocumentElementType2["FILE_UPLOAD"] = "file_upload";
|
|
290
|
+
return DocumentElementType2;
|
|
291
|
+
})(DocumentElementType || {});
|
|
292
|
+
var ListType = /* @__PURE__ */ ((ListType2) => {
|
|
293
|
+
ListType2["ORDERED"] = "ordered";
|
|
294
|
+
ListType2["UNORDERED"] = "unordered";
|
|
295
|
+
return ListType2;
|
|
296
|
+
})(ListType || {});
|
|
297
|
+
var HeadingLevel = /* @__PURE__ */ ((HeadingLevel2) => {
|
|
298
|
+
HeadingLevel2["H1"] = "h1";
|
|
299
|
+
HeadingLevel2["H2"] = "h2";
|
|
300
|
+
HeadingLevel2["H3"] = "h3";
|
|
301
|
+
HeadingLevel2["H4"] = "h4";
|
|
302
|
+
HeadingLevel2["H5"] = "h5";
|
|
303
|
+
HeadingLevel2["H6"] = "h6";
|
|
304
|
+
return HeadingLevel2;
|
|
305
|
+
})(HeadingLevel || {});
|
|
306
|
+
var DynamicVariable = /* @__PURE__ */ ((DynamicVariable2) => {
|
|
307
|
+
DynamicVariable2["PATIENT_NAME"] = "[PATIENT_NAME]";
|
|
308
|
+
DynamicVariable2["DOCTOR_NAME"] = "[DOCTOR_NAME]";
|
|
309
|
+
DynamicVariable2["CLINIC_NAME"] = "[CLINIC_NAME]";
|
|
310
|
+
DynamicVariable2["PATIENT_BIRTHDAY"] = "[PATIENT_BIRTHDAY]";
|
|
311
|
+
DynamicVariable2["APPOINTMENT_DATE"] = "[APPOINTMENT_DATE]";
|
|
312
|
+
DynamicVariable2["CURRENT_DATE"] = "[CURRENT_DATE]";
|
|
313
|
+
DynamicVariable2["PROCEDURE_NAME"] = "[PROCEDURE_NAME]";
|
|
314
|
+
DynamicVariable2["PROCEDURE_DESCRIPTION"] = "[PROCEDURE_DESCRIPTION]";
|
|
315
|
+
DynamicVariable2["PROCEDURE_COST"] = "[PROCEDURE_COST]";
|
|
316
|
+
DynamicVariable2["PROCEDURE_DURATION"] = "[PROCEDURE_DURATION]";
|
|
317
|
+
DynamicVariable2["PROCEDURE_RISK"] = "[PROCEDURE_RISK]";
|
|
318
|
+
return DynamicVariable2;
|
|
319
|
+
})(DynamicVariable || {});
|
|
320
|
+
var FilledDocumentStatus = /* @__PURE__ */ ((FilledDocumentStatus2) => {
|
|
321
|
+
FilledDocumentStatus2["DRAFT"] = "draft";
|
|
322
|
+
FilledDocumentStatus2["SKIPPED"] = "skipped";
|
|
323
|
+
FilledDocumentStatus2["PENDING"] = "pending";
|
|
324
|
+
FilledDocumentStatus2["COMPLETED"] = "completed";
|
|
325
|
+
FilledDocumentStatus2["SIGNED"] = "signed";
|
|
326
|
+
FilledDocumentStatus2["REJECTED"] = "rejected";
|
|
327
|
+
return FilledDocumentStatus2;
|
|
328
|
+
})(FilledDocumentStatus || {});
|
|
329
|
+
|
|
330
|
+
// src/validations/documentation-templates/template.schema.ts
|
|
331
|
+
var baseElementSchema = import_zod.z.object({
|
|
332
|
+
id: import_zod.z.string().optional(),
|
|
333
|
+
// Make id optional so we can omit it later
|
|
334
|
+
type: import_zod.z.nativeEnum(DocumentElementType),
|
|
335
|
+
required: import_zod.z.boolean().optional()
|
|
336
|
+
});
|
|
337
|
+
var headingElementSchema = baseElementSchema.extend({
|
|
338
|
+
type: import_zod.z.literal("heading" /* HEADING */),
|
|
339
|
+
text: import_zod.z.string().min(1).max(200),
|
|
340
|
+
level: import_zod.z.nativeEnum(HeadingLevel)
|
|
341
|
+
});
|
|
342
|
+
var paragraphElementSchema = baseElementSchema.extend({
|
|
343
|
+
type: import_zod.z.literal("paragraph" /* PARAGRAPH */),
|
|
344
|
+
text: import_zod.z.string().min(1).max(5e3)
|
|
345
|
+
});
|
|
346
|
+
var listElementSchema = baseElementSchema.extend({
|
|
347
|
+
type: import_zod.z.literal("list" /* LIST */),
|
|
348
|
+
items: import_zod.z.array(import_zod.z.string().min(1).max(500)).min(1).max(100),
|
|
349
|
+
listType: import_zod.z.nativeEnum(ListType)
|
|
350
|
+
});
|
|
351
|
+
var dynamicTextElementSchema = baseElementSchema.extend({
|
|
352
|
+
type: import_zod.z.literal("dynamic_text" /* DYNAMIC_TEXT */),
|
|
353
|
+
text: import_zod.z.string().min(1).max(5e3)
|
|
354
|
+
});
|
|
355
|
+
var binaryChoiceElementSchema = baseElementSchema.extend({
|
|
356
|
+
type: import_zod.z.literal("binary_choice" /* BINARY_CHOICE */),
|
|
357
|
+
question: import_zod.z.string().min(1).max(500),
|
|
358
|
+
defaultValue: import_zod.z.boolean().optional()
|
|
359
|
+
});
|
|
360
|
+
var multipleChoiceElementSchema = baseElementSchema.extend({
|
|
361
|
+
type: import_zod.z.literal("multiple_choice" /* MULTIPLE_CHOICE */),
|
|
362
|
+
question: import_zod.z.string().min(1).max(500),
|
|
363
|
+
options: import_zod.z.array(import_zod.z.string().min(1).max(200)).min(2).max(50),
|
|
364
|
+
defaultValues: import_zod.z.array(import_zod.z.string()).optional()
|
|
365
|
+
});
|
|
366
|
+
var singleChoiceElementSchema = baseElementSchema.extend({
|
|
367
|
+
type: import_zod.z.literal("single_choice" /* SINGLE_CHOICE */),
|
|
368
|
+
question: import_zod.z.string().min(1).max(500),
|
|
369
|
+
options: import_zod.z.array(import_zod.z.string().min(1).max(200)).min(2).max(50),
|
|
370
|
+
defaultValue: import_zod.z.string().optional()
|
|
371
|
+
});
|
|
372
|
+
var ratingScaleElementSchema = baseElementSchema.extend({
|
|
373
|
+
type: import_zod.z.literal("rating_scale" /* RATING_SCALE */),
|
|
374
|
+
question: import_zod.z.string().min(1).max(500),
|
|
375
|
+
min: import_zod.z.number().int().min(0).max(10),
|
|
376
|
+
max: import_zod.z.number().int().min(1).max(10),
|
|
377
|
+
labels: import_zod.z.record(import_zod.z.string()).optional(),
|
|
378
|
+
defaultValue: import_zod.z.number().int().optional()
|
|
379
|
+
});
|
|
380
|
+
var textInputElementSchema = baseElementSchema.extend({
|
|
381
|
+
type: import_zod.z.literal("text_input" /* TEXT_INPUT */),
|
|
382
|
+
label: import_zod.z.string().min(1).max(200),
|
|
383
|
+
placeholder: import_zod.z.string().max(200).optional(),
|
|
384
|
+
multiline: import_zod.z.boolean().optional(),
|
|
385
|
+
defaultValue: import_zod.z.string().optional()
|
|
386
|
+
});
|
|
387
|
+
var datePickerElementSchema = baseElementSchema.extend({
|
|
388
|
+
type: import_zod.z.literal("date_picker" /* DATE_PICKER */),
|
|
389
|
+
label: import_zod.z.string().min(1).max(200),
|
|
390
|
+
defaultValue: import_zod.z.string().optional()
|
|
391
|
+
// ISO date string
|
|
392
|
+
});
|
|
393
|
+
var signatureElementSchema = baseElementSchema.extend({
|
|
394
|
+
type: import_zod.z.literal("signature" /* SIGNATURE */),
|
|
395
|
+
label: import_zod.z.string().min(1).max(200)
|
|
396
|
+
});
|
|
397
|
+
var digitalSignatureElementSchema = baseElementSchema.extend({
|
|
398
|
+
type: import_zod.z.literal("digital_signature" /* DITIGAL_SIGNATURE */),
|
|
399
|
+
// Matching your type enum
|
|
400
|
+
label: import_zod.z.string().min(1).max(200)
|
|
401
|
+
});
|
|
402
|
+
var fileUploadElementSchema = baseElementSchema.extend({
|
|
403
|
+
type: import_zod.z.literal("file_upload" /* FILE_UPLOAD */),
|
|
404
|
+
label: import_zod.z.string().min(1).max(200),
|
|
405
|
+
allowedFileTypes: import_zod.z.array(import_zod.z.string()).optional(),
|
|
406
|
+
maxFileSizeMB: import_zod.z.number().positive().optional()
|
|
407
|
+
});
|
|
408
|
+
var documentElementSchema = import_zod.z.discriminatedUnion("type", [
|
|
409
|
+
headingElementSchema,
|
|
410
|
+
paragraphElementSchema,
|
|
411
|
+
listElementSchema,
|
|
412
|
+
dynamicTextElementSchema,
|
|
413
|
+
binaryChoiceElementSchema,
|
|
414
|
+
multipleChoiceElementSchema,
|
|
415
|
+
singleChoiceElementSchema,
|
|
416
|
+
ratingScaleElementSchema,
|
|
417
|
+
textInputElementSchema,
|
|
418
|
+
datePickerElementSchema,
|
|
419
|
+
signatureElementSchema,
|
|
420
|
+
digitalSignatureElementSchema,
|
|
421
|
+
fileUploadElementSchema
|
|
422
|
+
]);
|
|
423
|
+
var documentElementWithoutIdSchema = import_zod.z.discriminatedUnion("type", [
|
|
424
|
+
headingElementSchema.omit({ id: true }),
|
|
425
|
+
paragraphElementSchema.omit({ id: true }),
|
|
426
|
+
listElementSchema.omit({ id: true }),
|
|
427
|
+
dynamicTextElementSchema.omit({ id: true }),
|
|
428
|
+
binaryChoiceElementSchema.omit({ id: true }),
|
|
429
|
+
multipleChoiceElementSchema.omit({ id: true }),
|
|
430
|
+
singleChoiceElementSchema.omit({ id: true }),
|
|
431
|
+
ratingScaleElementSchema.omit({ id: true }),
|
|
432
|
+
textInputElementSchema.omit({ id: true }),
|
|
433
|
+
datePickerElementSchema.omit({ id: true }),
|
|
434
|
+
signatureElementSchema.omit({ id: true }),
|
|
435
|
+
digitalSignatureElementSchema.omit({ id: true }),
|
|
436
|
+
fileUploadElementSchema.omit({ id: true })
|
|
437
|
+
]);
|
|
438
|
+
var createDocumentTemplateSchema = import_zod.z.object({
|
|
439
|
+
title: import_zod.z.string().min(1).max(200),
|
|
440
|
+
description: import_zod.z.string().max(1e3).optional(),
|
|
441
|
+
elements: import_zod.z.array(documentElementWithoutIdSchema).min(1).max(100),
|
|
442
|
+
tags: import_zod.z.array(import_zod.z.string().min(1).max(50)).max(20).optional(),
|
|
443
|
+
isUserForm: import_zod.z.boolean().optional().default(false),
|
|
444
|
+
isRequired: import_zod.z.boolean().optional().default(false),
|
|
445
|
+
sortingOrder: import_zod.z.number().int().optional().default(0)
|
|
446
|
+
});
|
|
447
|
+
var updateDocumentTemplateSchema = import_zod.z.object({
|
|
448
|
+
title: import_zod.z.string().min(1).max(200).optional(),
|
|
449
|
+
description: import_zod.z.string().max(1e3).optional(),
|
|
450
|
+
elements: import_zod.z.array(documentElementWithoutIdSchema).min(1).max(100).optional(),
|
|
451
|
+
tags: import_zod.z.array(import_zod.z.string().min(1).max(50)).max(20).optional(),
|
|
452
|
+
isActive: import_zod.z.boolean().optional(),
|
|
453
|
+
isUserForm: import_zod.z.boolean().optional(),
|
|
454
|
+
isRequired: import_zod.z.boolean().optional(),
|
|
455
|
+
sortingOrder: import_zod.z.number().int().optional()
|
|
456
|
+
});
|
|
457
|
+
var documentTemplateSchema = import_zod.z.object({
|
|
458
|
+
id: import_zod.z.string(),
|
|
459
|
+
title: import_zod.z.string().min(1).max(200),
|
|
460
|
+
description: import_zod.z.string().max(1e3).optional(),
|
|
461
|
+
createdAt: import_zod.z.number(),
|
|
462
|
+
updatedAt: import_zod.z.number(),
|
|
463
|
+
createdBy: import_zod.z.string(),
|
|
464
|
+
elements: import_zod.z.array(documentElementSchema),
|
|
465
|
+
tags: import_zod.z.array(import_zod.z.string().min(1).max(50)).max(20).optional(),
|
|
466
|
+
version: import_zod.z.number().int().positive(),
|
|
467
|
+
isActive: import_zod.z.boolean(),
|
|
468
|
+
isUserForm: import_zod.z.boolean().optional().default(false),
|
|
469
|
+
isRequired: import_zod.z.boolean().optional().default(false),
|
|
470
|
+
sortingOrder: import_zod.z.number().int().optional().default(0)
|
|
471
|
+
});
|
|
472
|
+
var filledDocumentStatusSchema = import_zod.z.nativeEnum(FilledDocumentStatus);
|
|
473
|
+
var filledDocumentSchema = import_zod.z.object({
|
|
474
|
+
id: import_zod.z.string(),
|
|
475
|
+
templateId: import_zod.z.string(),
|
|
476
|
+
templateVersion: import_zod.z.number(),
|
|
477
|
+
isUserForm: import_zod.z.boolean(),
|
|
478
|
+
procedureId: import_zod.z.string(),
|
|
479
|
+
appointmentId: import_zod.z.string(),
|
|
480
|
+
patientId: import_zod.z.string(),
|
|
481
|
+
practitionerId: import_zod.z.string(),
|
|
482
|
+
clinicId: import_zod.z.string(),
|
|
483
|
+
createdAt: import_zod.z.number(),
|
|
484
|
+
updatedAt: import_zod.z.number(),
|
|
485
|
+
values: import_zod.z.record(import_zod.z.string(), import_zod.z.any()),
|
|
486
|
+
status: filledDocumentStatusSchema
|
|
487
|
+
});
|
|
488
|
+
var createFilledDocumentDataSchema = import_zod.z.object({
|
|
489
|
+
templateId: import_zod.z.string(),
|
|
490
|
+
procedureId: import_zod.z.string(),
|
|
491
|
+
appointmentId: import_zod.z.string(),
|
|
492
|
+
patientId: import_zod.z.string(),
|
|
493
|
+
practitionerId: import_zod.z.string(),
|
|
494
|
+
clinicId: import_zod.z.string(),
|
|
495
|
+
values: import_zod.z.record(import_zod.z.string(), import_zod.z.any()).optional().default({}),
|
|
496
|
+
status: filledDocumentStatusSchema.optional().default("draft" /* DRAFT */)
|
|
497
|
+
});
|
|
498
|
+
var updateFilledDocumentDataSchema = import_zod.z.object({
|
|
499
|
+
values: import_zod.z.record(import_zod.z.string(), import_zod.z.any()).optional(),
|
|
500
|
+
status: filledDocumentStatusSchema.optional()
|
|
501
|
+
});
|
|
502
|
+
|
|
252
503
|
// src/validations/appointment.schema.ts
|
|
253
|
-
var
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
504
|
+
var MIN_STRING_LENGTH = 1;
|
|
505
|
+
var MAX_STRING_LENGTH = 1024;
|
|
506
|
+
var MAX_STRING_LENGTH_LONG = 4096;
|
|
507
|
+
var MAX_ARRAY_LENGTH = 100;
|
|
508
|
+
var appointmentStatusSchema = import_zod2.z.nativeEnum(AppointmentStatus);
|
|
509
|
+
var paymentStatusSchema = import_zod2.z.nativeEnum(PaymentStatus);
|
|
510
|
+
var mediaTypeSchema = import_zod2.z.nativeEnum(MediaType);
|
|
511
|
+
var appointmentMediaItemSchema = import_zod2.z.object({
|
|
512
|
+
id: import_zod2.z.string().min(MIN_STRING_LENGTH, "Media item ID is required"),
|
|
513
|
+
type: mediaTypeSchema,
|
|
514
|
+
url: import_zod2.z.string().url("Media URL must be a valid URL"),
|
|
515
|
+
fileName: import_zod2.z.string().optional(),
|
|
516
|
+
uploadedAt: import_zod2.z.any().refine(
|
|
517
|
+
(val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
|
|
518
|
+
"uploadedAt must be a valid timestamp or Date object"
|
|
519
|
+
),
|
|
520
|
+
uploadedBy: import_zod2.z.string().min(MIN_STRING_LENGTH, "Uploaded by user ID is required"),
|
|
521
|
+
description: import_zod2.z.string().max(MAX_STRING_LENGTH, "Description too long").optional()
|
|
522
|
+
});
|
|
523
|
+
var procedureExtendedInfoSchema = import_zod2.z.object({
|
|
524
|
+
id: import_zod2.z.string().min(MIN_STRING_LENGTH),
|
|
525
|
+
name: import_zod2.z.string().min(MIN_STRING_LENGTH),
|
|
526
|
+
description: import_zod2.z.string(),
|
|
527
|
+
cost: import_zod2.z.number().min(0),
|
|
528
|
+
duration: import_zod2.z.number().min(0),
|
|
529
|
+
procedureFamily: import_zod2.z.any(),
|
|
530
|
+
procedureCategoryId: import_zod2.z.string(),
|
|
531
|
+
procedureCategoryName: import_zod2.z.string(),
|
|
532
|
+
procedureSubCategoryId: import_zod2.z.string(),
|
|
533
|
+
procedureSubCategoryName: import_zod2.z.string(),
|
|
534
|
+
procedureTechnologyId: import_zod2.z.string(),
|
|
535
|
+
procedureTechnologyName: import_zod2.z.string(),
|
|
536
|
+
procedureProductBrandId: import_zod2.z.string(),
|
|
537
|
+
procedureProductBrandName: import_zod2.z.string(),
|
|
538
|
+
procedureProductId: import_zod2.z.string(),
|
|
539
|
+
procedureProductName: import_zod2.z.string()
|
|
540
|
+
});
|
|
541
|
+
var linkedFormInfoSchema = import_zod2.z.object({
|
|
542
|
+
formId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Form ID is required"),
|
|
543
|
+
templateId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Template ID is required"),
|
|
544
|
+
templateVersion: import_zod2.z.number().int().positive("Template version must be a positive integer"),
|
|
545
|
+
title: import_zod2.z.string().min(MIN_STRING_LENGTH, "Form title is required"),
|
|
546
|
+
isUserForm: import_zod2.z.boolean(),
|
|
547
|
+
status: filledDocumentStatusSchema,
|
|
548
|
+
path: import_zod2.z.string().min(MIN_STRING_LENGTH, "Form path is required"),
|
|
549
|
+
submittedAt: import_zod2.z.any().refine(
|
|
550
|
+
(val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
|
|
551
|
+
"submittedAt must be a valid timestamp or Date object"
|
|
552
|
+
).optional(),
|
|
553
|
+
completedAt: import_zod2.z.any().refine(
|
|
554
|
+
(val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
|
|
555
|
+
"completedAt must be a valid timestamp or Date object"
|
|
556
|
+
).optional()
|
|
557
|
+
});
|
|
558
|
+
var patientReviewInfoSchema = import_zod2.z.object({
|
|
559
|
+
reviewId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Review ID is required"),
|
|
560
|
+
rating: import_zod2.z.number().min(1).max(5, "Rating must be between 1 and 5"),
|
|
561
|
+
comment: import_zod2.z.string().max(MAX_STRING_LENGTH_LONG, "Comment too long").optional(),
|
|
562
|
+
reviewedAt: import_zod2.z.any().refine(
|
|
563
|
+
(val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
|
|
564
|
+
"reviewedAt must be a valid timestamp or Date object"
|
|
565
|
+
)
|
|
566
|
+
});
|
|
567
|
+
var finalizedDetailsSchema = import_zod2.z.object({
|
|
568
|
+
by: import_zod2.z.string().min(MIN_STRING_LENGTH, "Finalized by user ID is required"),
|
|
569
|
+
at: import_zod2.z.any().refine(
|
|
570
|
+
(val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
|
|
571
|
+
"Finalized at must be a valid timestamp or Date object"
|
|
572
|
+
),
|
|
573
|
+
notes: import_zod2.z.string().max(MAX_STRING_LENGTH_LONG, "Finalization notes too long").optional()
|
|
574
|
+
});
|
|
575
|
+
var createAppointmentSchema = import_zod2.z.object({
|
|
576
|
+
calendarEventId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Calendar event ID is required"),
|
|
577
|
+
clinicBranchId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Clinic branch ID is required"),
|
|
578
|
+
practitionerId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Practitioner ID is required"),
|
|
579
|
+
patientId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Patient ID is required"),
|
|
580
|
+
procedureId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Procedure ID is required"),
|
|
581
|
+
appointmentStartTime: import_zod2.z.any().refine(
|
|
582
|
+
(val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
|
|
583
|
+
"Appointment start time must be a valid timestamp or Date object"
|
|
262
584
|
),
|
|
263
|
-
appointmentEndTime:
|
|
264
|
-
(val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0,
|
|
265
|
-
"Appointment end time must be a valid timestamp"
|
|
585
|
+
appointmentEndTime: import_zod2.z.any().refine(
|
|
586
|
+
(val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
|
|
587
|
+
"Appointment end time must be a valid timestamp or Date object"
|
|
266
588
|
),
|
|
267
|
-
cost:
|
|
268
|
-
currency:
|
|
269
|
-
patientNotes:
|
|
270
|
-
initialStatus:
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
}).optional().default("unpaid" /* UNPAID */)
|
|
589
|
+
cost: import_zod2.z.number().min(0, "Cost must be a non-negative number"),
|
|
590
|
+
currency: import_zod2.z.string().min(1, "Currency is required"),
|
|
591
|
+
patientNotes: import_zod2.z.string().max(MAX_STRING_LENGTH, "Patient notes too long").nullable().optional(),
|
|
592
|
+
initialStatus: appointmentStatusSchema,
|
|
593
|
+
initialPaymentStatus: paymentStatusSchema.optional().default("unpaid" /* UNPAID */)
|
|
594
|
+
}).refine((data) => data.appointmentEndTime > data.appointmentStartTime, {
|
|
595
|
+
message: "Appointment end time must be after start time",
|
|
596
|
+
path: ["appointmentEndTime"]
|
|
276
597
|
});
|
|
277
|
-
var updateAppointmentSchema =
|
|
278
|
-
status:
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
598
|
+
var updateAppointmentSchema = import_zod2.z.object({
|
|
599
|
+
status: appointmentStatusSchema.optional(),
|
|
600
|
+
confirmationTime: import_zod2.z.any().optional().nullable(),
|
|
601
|
+
cancellationTime: import_zod2.z.any().optional().nullable(),
|
|
602
|
+
rescheduleTime: import_zod2.z.any().optional().nullable(),
|
|
603
|
+
procedureActualStartTime: import_zod2.z.any().optional().nullable(),
|
|
604
|
+
actualDurationMinutes: import_zod2.z.number().int().positive("Duration must be a positive integer").optional(),
|
|
605
|
+
cancellationReason: import_zod2.z.string().max(MAX_STRING_LENGTH, "Cancellation reason too long").nullable().optional(),
|
|
606
|
+
canceledBy: import_zod2.z.enum(["patient", "clinic", "practitioner", "system"]).optional(),
|
|
607
|
+
internalNotes: import_zod2.z.string().max(MAX_STRING_LENGTH_LONG, "Internal notes too long").nullable().optional(),
|
|
608
|
+
patientNotes: import_zod2.z.any().optional().nullable(),
|
|
609
|
+
paymentStatus: paymentStatusSchema.optional(),
|
|
610
|
+
paymentTransactionId: import_zod2.z.any().optional().nullable(),
|
|
611
|
+
completedPreRequirements: import_zod2.z.union([import_zod2.z.array(import_zod2.z.string()), import_zod2.z.any()]).optional(),
|
|
612
|
+
completedPostRequirements: import_zod2.z.union([import_zod2.z.array(import_zod2.z.string()), import_zod2.z.any()]).optional(),
|
|
613
|
+
pendingUserFormsIds: import_zod2.z.union([import_zod2.z.array(import_zod2.z.string()), import_zod2.z.any()]).optional(),
|
|
614
|
+
appointmentStartTime: import_zod2.z.any().refine(
|
|
615
|
+
(val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
|
|
616
|
+
"Appointment start time must be a valid timestamp or Date object"
|
|
284
617
|
).optional(),
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
618
|
+
appointmentEndTime: import_zod2.z.any().refine(
|
|
619
|
+
(val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
|
|
620
|
+
"Appointment end time must be a valid timestamp or Date object"
|
|
621
|
+
).optional(),
|
|
622
|
+
calendarEventId: import_zod2.z.string().min(MIN_STRING_LENGTH).optional(),
|
|
623
|
+
cost: import_zod2.z.number().min(0).optional(),
|
|
624
|
+
clinicBranchId: import_zod2.z.string().min(MIN_STRING_LENGTH).optional(),
|
|
625
|
+
practitionerId: import_zod2.z.string().min(MIN_STRING_LENGTH).optional(),
|
|
626
|
+
linkedForms: import_zod2.z.union([import_zod2.z.array(linkedFormInfoSchema).max(MAX_ARRAY_LENGTH), import_zod2.z.any()]).optional(),
|
|
627
|
+
media: import_zod2.z.union([
|
|
628
|
+
import_zod2.z.array(appointmentMediaItemSchema).max(MAX_ARRAY_LENGTH),
|
|
629
|
+
import_zod2.z.any()
|
|
630
|
+
]).optional(),
|
|
631
|
+
reviewInfo: import_zod2.z.union([patientReviewInfoSchema.nullable(), import_zod2.z.any()]).optional(),
|
|
632
|
+
finalizedDetails: import_zod2.z.union([finalizedDetailsSchema.nullable(), import_zod2.z.any()]).optional(),
|
|
633
|
+
isArchived: import_zod2.z.boolean().optional(),
|
|
634
|
+
updatedAt: import_zod2.z.any().optional()
|
|
295
635
|
}).refine(
|
|
296
636
|
(data) => {
|
|
297
|
-
if (data.status === "canceled_clinic" /* CANCELED_CLINIC */ || data.status === "canceled_patient" /* CANCELED_PATIENT */) {
|
|
637
|
+
if (data.status === "canceled_clinic" /* CANCELED_CLINIC */ || data.status === "canceled_patient" /* CANCELED_PATIENT */ || data.status === "canceled_patient_rescheduled" /* CANCELED_PATIENT_RESCHEDULED */) {
|
|
298
638
|
return !!data.cancellationReason && !!data.canceledBy;
|
|
299
639
|
}
|
|
300
640
|
return true;
|
|
301
641
|
},
|
|
302
642
|
{
|
|
303
|
-
message: "Cancellation reason and canceled by must be provided when canceling an appointment",
|
|
643
|
+
message: "Cancellation reason and canceled by must be provided when canceling an appointment with patient or clinic origin.",
|
|
304
644
|
path: ["status"]
|
|
305
645
|
}
|
|
646
|
+
).refine(
|
|
647
|
+
(data) => {
|
|
648
|
+
if (data.appointmentStartTime && data.appointmentEndTime) {
|
|
649
|
+
return data.appointmentEndTime > data.appointmentStartTime;
|
|
650
|
+
}
|
|
651
|
+
return true;
|
|
652
|
+
},
|
|
653
|
+
{
|
|
654
|
+
message: "Appointment end time must be after start time if both are provided",
|
|
655
|
+
path: ["appointmentEndTime"]
|
|
656
|
+
}
|
|
306
657
|
);
|
|
307
|
-
var searchAppointmentsSchema =
|
|
308
|
-
patientId:
|
|
309
|
-
practitionerId:
|
|
310
|
-
clinicBranchId:
|
|
311
|
-
startDate:
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
658
|
+
var searchAppointmentsSchema = import_zod2.z.object({
|
|
659
|
+
patientId: import_zod2.z.string().optional(),
|
|
660
|
+
practitionerId: import_zod2.z.string().optional(),
|
|
661
|
+
clinicBranchId: import_zod2.z.string().optional(),
|
|
662
|
+
startDate: import_zod2.z.any().refine(
|
|
663
|
+
(val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
|
|
664
|
+
"Start date must be a valid timestamp or Date object"
|
|
665
|
+
).optional(),
|
|
666
|
+
endDate: import_zod2.z.any().refine(
|
|
667
|
+
(val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
|
|
668
|
+
"End date must be a valid timestamp or Date object"
|
|
669
|
+
).optional(),
|
|
670
|
+
status: import_zod2.z.union([
|
|
671
|
+
appointmentStatusSchema,
|
|
672
|
+
import_zod2.z.array(appointmentStatusSchema).nonempty()
|
|
316
673
|
]).optional(),
|
|
317
|
-
limit:
|
|
318
|
-
startAfter:
|
|
674
|
+
limit: import_zod2.z.number().positive().int().optional().default(20),
|
|
675
|
+
startAfter: import_zod2.z.any().optional()
|
|
319
676
|
}).refine(
|
|
320
677
|
(data) => {
|
|
321
|
-
|
|
678
|
+
if (!data.startDate && !data.endDate && !data.status) {
|
|
679
|
+
return !!(data.patientId || data.practitionerId || data.clinicBranchId);
|
|
680
|
+
}
|
|
681
|
+
return true;
|
|
682
|
+
},
|
|
683
|
+
{
|
|
684
|
+
message: "At least one of patientId, practitionerId, or clinicBranchId must be provided if no date or status filters are set.",
|
|
685
|
+
path: ["patientId"]
|
|
686
|
+
}
|
|
687
|
+
).refine(
|
|
688
|
+
(data) => {
|
|
689
|
+
if (data.startDate && data.endDate) {
|
|
690
|
+
return data.endDate >= data.startDate;
|
|
691
|
+
}
|
|
692
|
+
return true;
|
|
322
693
|
},
|
|
323
694
|
{
|
|
324
|
-
message: "
|
|
325
|
-
path: ["
|
|
695
|
+
message: "End date must be after or the same as start date",
|
|
696
|
+
path: ["endDate"]
|
|
326
697
|
}
|
|
327
698
|
);
|
|
328
699
|
|
|
@@ -371,54 +742,6 @@ var getFirebaseApp = async () => {
|
|
|
371
742
|
var import_auth5 = require("firebase/auth");
|
|
372
743
|
var import_firestore22 = require("firebase/firestore");
|
|
373
744
|
|
|
374
|
-
// src/types/documentation-templates/index.ts
|
|
375
|
-
var DOCUMENTATION_TEMPLATES_COLLECTION = "documentation-templates";
|
|
376
|
-
var FILLED_DOCUMENTS_COLLECTION = "filled-documents";
|
|
377
|
-
var DocumentElementType = /* @__PURE__ */ ((DocumentElementType2) => {
|
|
378
|
-
DocumentElementType2["HEADING"] = "heading";
|
|
379
|
-
DocumentElementType2["PARAGRAPH"] = "paragraph";
|
|
380
|
-
DocumentElementType2["LIST"] = "list";
|
|
381
|
-
DocumentElementType2["DYNAMIC_TEXT"] = "dynamic_text";
|
|
382
|
-
DocumentElementType2["BINARY_CHOICE"] = "binary_choice";
|
|
383
|
-
DocumentElementType2["MULTIPLE_CHOICE"] = "multiple_choice";
|
|
384
|
-
DocumentElementType2["SINGLE_CHOICE"] = "single_choice";
|
|
385
|
-
DocumentElementType2["RATING_SCALE"] = "rating_scale";
|
|
386
|
-
DocumentElementType2["TEXT_INPUT"] = "text_input";
|
|
387
|
-
DocumentElementType2["DATE_PICKER"] = "date_picker";
|
|
388
|
-
DocumentElementType2["SIGNATURE"] = "signature";
|
|
389
|
-
DocumentElementType2["FILE_UPLOAD"] = "file_upload";
|
|
390
|
-
return DocumentElementType2;
|
|
391
|
-
})(DocumentElementType || {});
|
|
392
|
-
var ListType = /* @__PURE__ */ ((ListType2) => {
|
|
393
|
-
ListType2["ORDERED"] = "ordered";
|
|
394
|
-
ListType2["UNORDERED"] = "unordered";
|
|
395
|
-
return ListType2;
|
|
396
|
-
})(ListType || {});
|
|
397
|
-
var HeadingLevel = /* @__PURE__ */ ((HeadingLevel2) => {
|
|
398
|
-
HeadingLevel2["H1"] = "h1";
|
|
399
|
-
HeadingLevel2["H2"] = "h2";
|
|
400
|
-
HeadingLevel2["H3"] = "h3";
|
|
401
|
-
HeadingLevel2["H4"] = "h4";
|
|
402
|
-
HeadingLevel2["H5"] = "h5";
|
|
403
|
-
HeadingLevel2["H6"] = "h6";
|
|
404
|
-
return HeadingLevel2;
|
|
405
|
-
})(HeadingLevel || {});
|
|
406
|
-
var DynamicVariable = /* @__PURE__ */ ((DynamicVariable2) => {
|
|
407
|
-
DynamicVariable2["PATIENT_NAME"] = "[PATIENT_NAME]";
|
|
408
|
-
DynamicVariable2["DOCTOR_NAME"] = "[DOCTOR_NAME]";
|
|
409
|
-
DynamicVariable2["CLINIC_NAME"] = "[CLINIC_NAME]";
|
|
410
|
-
DynamicVariable2["PATIENT_BIRTHDAY"] = "[PATIENT_BIRTHDAY]";
|
|
411
|
-
DynamicVariable2["APPOINTMENT_DATE"] = "[APPOINTMENT_DATE]";
|
|
412
|
-
DynamicVariable2["CURRENT_DATE"] = "[CURRENT_DATE]";
|
|
413
|
-
return DynamicVariable2;
|
|
414
|
-
})(DynamicVariable || {});
|
|
415
|
-
var FilledDocumentStatus = /* @__PURE__ */ ((FilledDocumentStatus2) => {
|
|
416
|
-
FilledDocumentStatus2["DRAFT"] = "draft";
|
|
417
|
-
FilledDocumentStatus2["COMPLETED"] = "completed";
|
|
418
|
-
FilledDocumentStatus2["SIGNED"] = "signed";
|
|
419
|
-
return FilledDocumentStatus2;
|
|
420
|
-
})(FilledDocumentStatus || {});
|
|
421
|
-
|
|
422
745
|
// src/types/calendar/index.ts
|
|
423
746
|
var CalendarEventStatus = /* @__PURE__ */ ((CalendarEventStatus4) => {
|
|
424
747
|
CalendarEventStatus4["PENDING"] = "pending";
|
|
@@ -465,136 +788,6 @@ var import_zod19 = require("zod");
|
|
|
465
788
|
|
|
466
789
|
// src/validations/schemas.ts
|
|
467
790
|
var import_zod3 = require("zod");
|
|
468
|
-
|
|
469
|
-
// src/validations/documentation-templates/template.schema.ts
|
|
470
|
-
var import_zod2 = require("zod");
|
|
471
|
-
var baseElementSchema = import_zod2.z.object({
|
|
472
|
-
id: import_zod2.z.string().optional(),
|
|
473
|
-
// Make id optional so we can omit it later
|
|
474
|
-
type: import_zod2.z.nativeEnum(DocumentElementType),
|
|
475
|
-
required: import_zod2.z.boolean().optional()
|
|
476
|
-
});
|
|
477
|
-
var headingElementSchema = baseElementSchema.extend({
|
|
478
|
-
type: import_zod2.z.literal("heading" /* HEADING */),
|
|
479
|
-
text: import_zod2.z.string().min(1).max(200),
|
|
480
|
-
level: import_zod2.z.nativeEnum(HeadingLevel)
|
|
481
|
-
});
|
|
482
|
-
var paragraphElementSchema = baseElementSchema.extend({
|
|
483
|
-
type: import_zod2.z.literal("paragraph" /* PARAGRAPH */),
|
|
484
|
-
text: import_zod2.z.string().min(1).max(5e3)
|
|
485
|
-
});
|
|
486
|
-
var listElementSchema = baseElementSchema.extend({
|
|
487
|
-
type: import_zod2.z.literal("list" /* LIST */),
|
|
488
|
-
items: import_zod2.z.array(import_zod2.z.string().min(1).max(500)).min(1).max(100),
|
|
489
|
-
listType: import_zod2.z.nativeEnum(ListType)
|
|
490
|
-
});
|
|
491
|
-
var dynamicTextElementSchema = baseElementSchema.extend({
|
|
492
|
-
type: import_zod2.z.literal("dynamic_text" /* DYNAMIC_TEXT */),
|
|
493
|
-
text: import_zod2.z.string().min(1).max(5e3)
|
|
494
|
-
});
|
|
495
|
-
var binaryChoiceElementSchema = baseElementSchema.extend({
|
|
496
|
-
type: import_zod2.z.literal("binary_choice" /* BINARY_CHOICE */),
|
|
497
|
-
question: import_zod2.z.string().min(1).max(500),
|
|
498
|
-
defaultValue: import_zod2.z.boolean().optional()
|
|
499
|
-
});
|
|
500
|
-
var multipleChoiceElementSchema = baseElementSchema.extend({
|
|
501
|
-
type: import_zod2.z.literal("multiple_choice" /* MULTIPLE_CHOICE */),
|
|
502
|
-
question: import_zod2.z.string().min(1).max(500),
|
|
503
|
-
options: import_zod2.z.array(import_zod2.z.string().min(1).max(200)).min(2).max(50),
|
|
504
|
-
defaultValues: import_zod2.z.array(import_zod2.z.string()).optional()
|
|
505
|
-
});
|
|
506
|
-
var singleChoiceElementSchema = baseElementSchema.extend({
|
|
507
|
-
type: import_zod2.z.literal("single_choice" /* SINGLE_CHOICE */),
|
|
508
|
-
question: import_zod2.z.string().min(1).max(500),
|
|
509
|
-
options: import_zod2.z.array(import_zod2.z.string().min(1).max(200)).min(2).max(50),
|
|
510
|
-
defaultValue: import_zod2.z.string().optional()
|
|
511
|
-
});
|
|
512
|
-
var ratingScaleElementSchema = baseElementSchema.extend({
|
|
513
|
-
type: import_zod2.z.literal("rating_scale" /* RATING_SCALE */),
|
|
514
|
-
question: import_zod2.z.string().min(1).max(500),
|
|
515
|
-
min: import_zod2.z.number().int().min(0).max(10),
|
|
516
|
-
max: import_zod2.z.number().int().min(1).max(10),
|
|
517
|
-
labels: import_zod2.z.record(import_zod2.z.string()).optional(),
|
|
518
|
-
defaultValue: import_zod2.z.number().int().optional()
|
|
519
|
-
});
|
|
520
|
-
var textInputElementSchema = baseElementSchema.extend({
|
|
521
|
-
type: import_zod2.z.literal("text_input" /* TEXT_INPUT */),
|
|
522
|
-
label: import_zod2.z.string().min(1).max(200),
|
|
523
|
-
placeholder: import_zod2.z.string().max(200).optional(),
|
|
524
|
-
multiline: import_zod2.z.boolean().optional(),
|
|
525
|
-
defaultValue: import_zod2.z.string().optional()
|
|
526
|
-
});
|
|
527
|
-
var datePickerElementSchema = baseElementSchema.extend({
|
|
528
|
-
type: import_zod2.z.literal("date_picker" /* DATE_PICKER */),
|
|
529
|
-
label: import_zod2.z.string().min(1).max(200),
|
|
530
|
-
defaultValue: import_zod2.z.string().optional()
|
|
531
|
-
// ISO date string
|
|
532
|
-
});
|
|
533
|
-
var signatureElementSchema = baseElementSchema.extend({
|
|
534
|
-
type: import_zod2.z.literal("signature" /* SIGNATURE */),
|
|
535
|
-
label: import_zod2.z.string().min(1).max(200)
|
|
536
|
-
});
|
|
537
|
-
var fileUploadElementSchema = baseElementSchema.extend({
|
|
538
|
-
type: import_zod2.z.literal("file_upload" /* FILE_UPLOAD */),
|
|
539
|
-
label: import_zod2.z.string().min(1).max(200),
|
|
540
|
-
allowedFileTypes: import_zod2.z.array(import_zod2.z.string()).optional(),
|
|
541
|
-
maxFileSizeMB: import_zod2.z.number().positive().optional()
|
|
542
|
-
});
|
|
543
|
-
var documentElementSchema = import_zod2.z.discriminatedUnion("type", [
|
|
544
|
-
headingElementSchema,
|
|
545
|
-
paragraphElementSchema,
|
|
546
|
-
listElementSchema,
|
|
547
|
-
dynamicTextElementSchema,
|
|
548
|
-
binaryChoiceElementSchema,
|
|
549
|
-
multipleChoiceElementSchema,
|
|
550
|
-
singleChoiceElementSchema,
|
|
551
|
-
ratingScaleElementSchema,
|
|
552
|
-
textInputElementSchema,
|
|
553
|
-
datePickerElementSchema,
|
|
554
|
-
signatureElementSchema,
|
|
555
|
-
fileUploadElementSchema
|
|
556
|
-
]);
|
|
557
|
-
var documentElementWithoutIdSchema = import_zod2.z.discriminatedUnion("type", [
|
|
558
|
-
headingElementSchema.omit({ id: true }),
|
|
559
|
-
paragraphElementSchema.omit({ id: true }),
|
|
560
|
-
listElementSchema.omit({ id: true }),
|
|
561
|
-
dynamicTextElementSchema.omit({ id: true }),
|
|
562
|
-
binaryChoiceElementSchema.omit({ id: true }),
|
|
563
|
-
multipleChoiceElementSchema.omit({ id: true }),
|
|
564
|
-
singleChoiceElementSchema.omit({ id: true }),
|
|
565
|
-
ratingScaleElementSchema.omit({ id: true }),
|
|
566
|
-
textInputElementSchema.omit({ id: true }),
|
|
567
|
-
datePickerElementSchema.omit({ id: true }),
|
|
568
|
-
signatureElementSchema.omit({ id: true }),
|
|
569
|
-
fileUploadElementSchema.omit({ id: true })
|
|
570
|
-
]);
|
|
571
|
-
var createDocumentTemplateSchema = import_zod2.z.object({
|
|
572
|
-
title: import_zod2.z.string().min(1).max(200),
|
|
573
|
-
description: import_zod2.z.string().max(1e3).optional(),
|
|
574
|
-
elements: import_zod2.z.array(documentElementWithoutIdSchema).min(1).max(100),
|
|
575
|
-
tags: import_zod2.z.array(import_zod2.z.string().min(1).max(50)).max(20).optional()
|
|
576
|
-
});
|
|
577
|
-
var updateDocumentTemplateSchema = import_zod2.z.object({
|
|
578
|
-
title: import_zod2.z.string().min(1).max(200).optional(),
|
|
579
|
-
description: import_zod2.z.string().max(1e3).optional(),
|
|
580
|
-
elements: import_zod2.z.array(documentElementWithoutIdSchema).min(1).max(100).optional(),
|
|
581
|
-
tags: import_zod2.z.array(import_zod2.z.string().min(1).max(50)).max(20).optional(),
|
|
582
|
-
isActive: import_zod2.z.boolean().optional()
|
|
583
|
-
});
|
|
584
|
-
var documentTemplateSchema = import_zod2.z.object({
|
|
585
|
-
id: import_zod2.z.string(),
|
|
586
|
-
title: import_zod2.z.string().min(1).max(200),
|
|
587
|
-
description: import_zod2.z.string().max(1e3).optional(),
|
|
588
|
-
createdAt: import_zod2.z.number(),
|
|
589
|
-
updatedAt: import_zod2.z.number(),
|
|
590
|
-
createdBy: import_zod2.z.string(),
|
|
591
|
-
elements: import_zod2.z.array(documentElementSchema),
|
|
592
|
-
tags: import_zod2.z.array(import_zod2.z.string().min(1).max(50)).max(20).optional(),
|
|
593
|
-
version: import_zod2.z.number().int().positive(),
|
|
594
|
-
isActive: import_zod2.z.boolean()
|
|
595
|
-
});
|
|
596
|
-
|
|
597
|
-
// src/validations/schemas.ts
|
|
598
791
|
var emailSchema = import_zod3.z.string().email("Invalid email format").min(5, "Email must be at least 5 characters").max(255, "Email must be less than 255 characters");
|
|
599
792
|
var passwordSchema = import_zod3.z.string().min(8, "Password must be at least 8 characters").max(100, "Password must be less than 100 characters").regex(
|
|
600
793
|
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d\w\W]{8,}$/,
|
|
@@ -1607,9 +1800,9 @@ var addAllergyUtil = async (db, patientId, data, userRef) => {
|
|
|
1607
1800
|
var updateAllergyUtil = async (db, patientId, data, userRef) => {
|
|
1608
1801
|
const validatedData = updateAllergySchema.parse(data);
|
|
1609
1802
|
const { allergyIndex, ...updateData } = validatedData;
|
|
1610
|
-
const
|
|
1611
|
-
if (!
|
|
1612
|
-
const medicalInfo =
|
|
1803
|
+
const doc33 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
|
|
1804
|
+
if (!doc33.exists()) throw new Error("Medical info not found");
|
|
1805
|
+
const medicalInfo = doc33.data();
|
|
1613
1806
|
if (allergyIndex >= medicalInfo.allergies.length) {
|
|
1614
1807
|
throw new Error("Invalid allergy index");
|
|
1615
1808
|
}
|
|
@@ -1625,9 +1818,9 @@ var updateAllergyUtil = async (db, patientId, data, userRef) => {
|
|
|
1625
1818
|
});
|
|
1626
1819
|
};
|
|
1627
1820
|
var removeAllergyUtil = async (db, patientId, allergyIndex, userRef) => {
|
|
1628
|
-
const
|
|
1629
|
-
if (!
|
|
1630
|
-
const medicalInfo =
|
|
1821
|
+
const doc33 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
|
|
1822
|
+
if (!doc33.exists()) throw new Error("Medical info not found");
|
|
1823
|
+
const medicalInfo = doc33.data();
|
|
1631
1824
|
if (allergyIndex >= medicalInfo.allergies.length) {
|
|
1632
1825
|
throw new Error("Invalid allergy index");
|
|
1633
1826
|
}
|
|
@@ -1652,9 +1845,9 @@ var addBlockingConditionUtil = async (db, patientId, data, userRef) => {
|
|
|
1652
1845
|
var updateBlockingConditionUtil = async (db, patientId, data, userRef) => {
|
|
1653
1846
|
const validatedData = updateBlockingConditionSchema.parse(data);
|
|
1654
1847
|
const { conditionIndex, ...updateData } = validatedData;
|
|
1655
|
-
const
|
|
1656
|
-
if (!
|
|
1657
|
-
const medicalInfo =
|
|
1848
|
+
const doc33 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
|
|
1849
|
+
if (!doc33.exists()) throw new Error("Medical info not found");
|
|
1850
|
+
const medicalInfo = doc33.data();
|
|
1658
1851
|
if (conditionIndex >= medicalInfo.blockingConditions.length) {
|
|
1659
1852
|
throw new Error("Invalid blocking condition index");
|
|
1660
1853
|
}
|
|
@@ -1670,9 +1863,9 @@ var updateBlockingConditionUtil = async (db, patientId, data, userRef) => {
|
|
|
1670
1863
|
});
|
|
1671
1864
|
};
|
|
1672
1865
|
var removeBlockingConditionUtil = async (db, patientId, conditionIndex, userRef) => {
|
|
1673
|
-
const
|
|
1674
|
-
if (!
|
|
1675
|
-
const medicalInfo =
|
|
1866
|
+
const doc33 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
|
|
1867
|
+
if (!doc33.exists()) throw new Error("Medical info not found");
|
|
1868
|
+
const medicalInfo = doc33.data();
|
|
1676
1869
|
if (conditionIndex >= medicalInfo.blockingConditions.length) {
|
|
1677
1870
|
throw new Error("Invalid blocking condition index");
|
|
1678
1871
|
}
|
|
@@ -1697,9 +1890,9 @@ var addContraindicationUtil = async (db, patientId, data, userRef) => {
|
|
|
1697
1890
|
var updateContraindicationUtil = async (db, patientId, data, userRef) => {
|
|
1698
1891
|
const validatedData = updateContraindicationSchema.parse(data);
|
|
1699
1892
|
const { contraindicationIndex, ...updateData } = validatedData;
|
|
1700
|
-
const
|
|
1701
|
-
if (!
|
|
1702
|
-
const medicalInfo =
|
|
1893
|
+
const doc33 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
|
|
1894
|
+
if (!doc33.exists()) throw new Error("Medical info not found");
|
|
1895
|
+
const medicalInfo = doc33.data();
|
|
1703
1896
|
if (contraindicationIndex >= medicalInfo.contraindications.length) {
|
|
1704
1897
|
throw new Error("Invalid contraindication index");
|
|
1705
1898
|
}
|
|
@@ -1715,9 +1908,9 @@ var updateContraindicationUtil = async (db, patientId, data, userRef) => {
|
|
|
1715
1908
|
});
|
|
1716
1909
|
};
|
|
1717
1910
|
var removeContraindicationUtil = async (db, patientId, contraindicationIndex, userRef) => {
|
|
1718
|
-
const
|
|
1719
|
-
if (!
|
|
1720
|
-
const medicalInfo =
|
|
1911
|
+
const doc33 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
|
|
1912
|
+
if (!doc33.exists()) throw new Error("Medical info not found");
|
|
1913
|
+
const medicalInfo = doc33.data();
|
|
1721
1914
|
if (contraindicationIndex >= medicalInfo.contraindications.length) {
|
|
1722
1915
|
throw new Error("Invalid contraindication index");
|
|
1723
1916
|
}
|
|
@@ -1742,9 +1935,9 @@ var addMedicationUtil = async (db, patientId, data, userRef) => {
|
|
|
1742
1935
|
var updateMedicationUtil = async (db, patientId, data, userRef) => {
|
|
1743
1936
|
const validatedData = updateMedicationSchema.parse(data);
|
|
1744
1937
|
const { medicationIndex, ...updateData } = validatedData;
|
|
1745
|
-
const
|
|
1746
|
-
if (!
|
|
1747
|
-
const medicalInfo =
|
|
1938
|
+
const doc33 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
|
|
1939
|
+
if (!doc33.exists()) throw new Error("Medical info not found");
|
|
1940
|
+
const medicalInfo = doc33.data();
|
|
1748
1941
|
if (medicationIndex >= medicalInfo.currentMedications.length) {
|
|
1749
1942
|
throw new Error("Invalid medication index");
|
|
1750
1943
|
}
|
|
@@ -1760,9 +1953,9 @@ var updateMedicationUtil = async (db, patientId, data, userRef) => {
|
|
|
1760
1953
|
});
|
|
1761
1954
|
};
|
|
1762
1955
|
var removeMedicationUtil = async (db, patientId, medicationIndex, userRef) => {
|
|
1763
|
-
const
|
|
1764
|
-
if (!
|
|
1765
|
-
const medicalInfo =
|
|
1956
|
+
const doc33 = await (0, import_firestore5.getDoc)(getMedicalInfoDocRef(db, patientId));
|
|
1957
|
+
if (!doc33.exists()) throw new Error("Medical info not found");
|
|
1958
|
+
const medicalInfo = doc33.data();
|
|
1766
1959
|
if (medicationIndex >= medicalInfo.currentMedications.length) {
|
|
1767
1960
|
throw new Error("Invalid medication index");
|
|
1768
1961
|
}
|
|
@@ -2040,7 +2233,7 @@ var searchPatientsUtil = async (db, params, requester) => {
|
|
|
2040
2233
|
try {
|
|
2041
2234
|
const finalQuery = (0, import_firestore6.query)(patientsCollectionRef, ...constraints);
|
|
2042
2235
|
const querySnapshot = await (0, import_firestore6.getDocs)(finalQuery);
|
|
2043
|
-
const patients = querySnapshot.docs.map((
|
|
2236
|
+
const patients = querySnapshot.docs.map((doc33) => doc33.data());
|
|
2044
2237
|
console.log(`[searchPatientsUtil] Found ${patients.length} patients matching criteria.`);
|
|
2045
2238
|
return patients;
|
|
2046
2239
|
} catch (error) {
|
|
@@ -2064,8 +2257,8 @@ var getAllPatientsUtil = async (db, options) => {
|
|
|
2064
2257
|
}
|
|
2065
2258
|
const patientsSnapshot = await (0, import_firestore6.getDocs)(q);
|
|
2066
2259
|
const patients = [];
|
|
2067
|
-
patientsSnapshot.forEach((
|
|
2068
|
-
patients.push(
|
|
2260
|
+
patientsSnapshot.forEach((doc33) => {
|
|
2261
|
+
patients.push(doc33.data());
|
|
2069
2262
|
});
|
|
2070
2263
|
console.log(`[getAllPatientsUtil] Found ${patients.length} patients`);
|
|
2071
2264
|
return patients;
|
|
@@ -2277,8 +2470,8 @@ var getPatientsByPractitionerUtil = async (db, practitionerId, options) => {
|
|
|
2277
2470
|
}
|
|
2278
2471
|
const patientsSnapshot = await (0, import_firestore9.getDocs)(q);
|
|
2279
2472
|
const patients = [];
|
|
2280
|
-
patientsSnapshot.forEach((
|
|
2281
|
-
patients.push(
|
|
2473
|
+
patientsSnapshot.forEach((doc33) => {
|
|
2474
|
+
patients.push(doc33.data());
|
|
2282
2475
|
});
|
|
2283
2476
|
console.log(
|
|
2284
2477
|
`[getPatientsByPractitionerUtil] Found ${patients.length} patients for practitioner ID: ${practitionerId}`
|
|
@@ -2366,8 +2559,8 @@ var getPatientsByClinicUtil = async (db, clinicId, options) => {
|
|
|
2366
2559
|
}
|
|
2367
2560
|
const patientsSnapshot = await (0, import_firestore10.getDocs)(q);
|
|
2368
2561
|
const patients = [];
|
|
2369
|
-
patientsSnapshot.forEach((
|
|
2370
|
-
patients.push(
|
|
2562
|
+
patientsSnapshot.forEach((doc33) => {
|
|
2563
|
+
patients.push(doc33.data());
|
|
2371
2564
|
});
|
|
2372
2565
|
console.log(
|
|
2373
2566
|
`[getPatientsByClinicUtil] Found ${patients.length} patients for clinic ID: ${clinicId}`
|
|
@@ -3480,7 +3673,7 @@ async function getClinicAdminsByGroup(db, clinicGroupId) {
|
|
|
3480
3673
|
(0, import_firestore13.where)("clinicGroupId", "==", clinicGroupId)
|
|
3481
3674
|
);
|
|
3482
3675
|
const querySnapshot = await (0, import_firestore13.getDocs)(q);
|
|
3483
|
-
return querySnapshot.docs.map((
|
|
3676
|
+
return querySnapshot.docs.map((doc33) => doc33.data());
|
|
3484
3677
|
}
|
|
3485
3678
|
async function updateClinicAdmin(db, adminId, data) {
|
|
3486
3679
|
const admin = await getClinicAdmin(db, adminId);
|
|
@@ -3741,6 +3934,8 @@ var ClinicAdminService = class extends BaseService {
|
|
|
3741
3934
|
this.getClinicService()
|
|
3742
3935
|
);
|
|
3743
3936
|
}
|
|
3937
|
+
// TODO: Add more methods for clinic admins for managing permissions, editing profiles by the admin, or by the clinic group owner and so on
|
|
3938
|
+
// Generally refactor admin permissions and clinic group permissions and systems for admin management
|
|
3744
3939
|
};
|
|
3745
3940
|
|
|
3746
3941
|
// src/services/practitioner/practitioner.service.ts
|
|
@@ -4177,7 +4372,7 @@ var PractitionerService = class extends BaseService {
|
|
|
4177
4372
|
(0, import_firestore15.where)("expiresAt", ">", import_firestore15.Timestamp.now())
|
|
4178
4373
|
);
|
|
4179
4374
|
const querySnapshot = await (0, import_firestore15.getDocs)(q);
|
|
4180
|
-
return querySnapshot.docs.map((
|
|
4375
|
+
return querySnapshot.docs.map((doc33) => doc33.data());
|
|
4181
4376
|
}
|
|
4182
4377
|
/**
|
|
4183
4378
|
* Gets a token by its string value and validates it
|
|
@@ -4260,7 +4455,7 @@ var PractitionerService = class extends BaseService {
|
|
|
4260
4455
|
(0, import_firestore15.where)("status", "==", "active" /* ACTIVE */)
|
|
4261
4456
|
);
|
|
4262
4457
|
const querySnapshot = await (0, import_firestore15.getDocs)(q);
|
|
4263
|
-
return querySnapshot.docs.map((
|
|
4458
|
+
return querySnapshot.docs.map((doc33) => doc33.data());
|
|
4264
4459
|
}
|
|
4265
4460
|
/**
|
|
4266
4461
|
* Dohvata sve zdravstvene radnike za određenu kliniku
|
|
@@ -4272,7 +4467,7 @@ var PractitionerService = class extends BaseService {
|
|
|
4272
4467
|
(0, import_firestore15.where)("isActive", "==", true)
|
|
4273
4468
|
);
|
|
4274
4469
|
const querySnapshot = await (0, import_firestore15.getDocs)(q);
|
|
4275
|
-
return querySnapshot.docs.map((
|
|
4470
|
+
return querySnapshot.docs.map((doc33) => doc33.data());
|
|
4276
4471
|
}
|
|
4277
4472
|
/**
|
|
4278
4473
|
* Dohvata sve draft zdravstvene radnike za određenu kliniku sa statusom DRAFT
|
|
@@ -4284,7 +4479,7 @@ var PractitionerService = class extends BaseService {
|
|
|
4284
4479
|
(0, import_firestore15.where)("status", "==", "draft" /* DRAFT */)
|
|
4285
4480
|
);
|
|
4286
4481
|
const querySnapshot = await (0, import_firestore15.getDocs)(q);
|
|
4287
|
-
return querySnapshot.docs.map((
|
|
4482
|
+
return querySnapshot.docs.map((doc33) => doc33.data());
|
|
4288
4483
|
}
|
|
4289
4484
|
/**
|
|
4290
4485
|
* Updates a practitioner
|
|
@@ -4466,7 +4661,7 @@ var PractitionerService = class extends BaseService {
|
|
|
4466
4661
|
);
|
|
4467
4662
|
const querySnapshot = await (0, import_firestore15.getDocs)(q);
|
|
4468
4663
|
const practitioners = querySnapshot.docs.map(
|
|
4469
|
-
(
|
|
4664
|
+
(doc33) => doc33.data()
|
|
4470
4665
|
);
|
|
4471
4666
|
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
4472
4667
|
return {
|
|
@@ -4537,8 +4732,8 @@ var PractitionerService = class extends BaseService {
|
|
|
4537
4732
|
console.log(
|
|
4538
4733
|
`[PRACTITIONER_SERVICE] Found ${querySnapshot.docs.length} practitioners with base query`
|
|
4539
4734
|
);
|
|
4540
|
-
let practitioners = querySnapshot.docs.map((
|
|
4541
|
-
return { ...
|
|
4735
|
+
let practitioners = querySnapshot.docs.map((doc33) => {
|
|
4736
|
+
return { ...doc33.data(), id: doc33.id };
|
|
4542
4737
|
});
|
|
4543
4738
|
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
4544
4739
|
if (filters.nameSearch && filters.nameSearch.trim() !== "") {
|
|
@@ -4792,7 +4987,7 @@ var UserService = class extends BaseService {
|
|
|
4792
4987
|
];
|
|
4793
4988
|
const q = (0, import_firestore16.query)((0, import_firestore16.collection)(this.db, USERS_COLLECTION), ...constraints);
|
|
4794
4989
|
const querySnapshot = await (0, import_firestore16.getDocs)(q);
|
|
4795
|
-
const users = querySnapshot.docs.map((
|
|
4990
|
+
const users = querySnapshot.docs.map((doc33) => doc33.data());
|
|
4796
4991
|
return Promise.all(users.map((userData) => userSchema.parse(userData)));
|
|
4797
4992
|
}
|
|
4798
4993
|
/**
|
|
@@ -5156,7 +5351,7 @@ async function getAllActiveGroups(db) {
|
|
|
5156
5351
|
(0, import_firestore17.where)("isActive", "==", true)
|
|
5157
5352
|
);
|
|
5158
5353
|
const querySnapshot = await (0, import_firestore17.getDocs)(q);
|
|
5159
|
-
return querySnapshot.docs.map((
|
|
5354
|
+
return querySnapshot.docs.map((doc33) => doc33.data());
|
|
5160
5355
|
}
|
|
5161
5356
|
async function updateClinicGroup(db, groupId, data, app) {
|
|
5162
5357
|
console.log("[CLINIC_GROUP] Updating clinic group", { groupId });
|
|
@@ -5528,6 +5723,11 @@ var ClinicGroupService = class extends BaseService {
|
|
|
5528
5723
|
this.app
|
|
5529
5724
|
);
|
|
5530
5725
|
}
|
|
5726
|
+
// TODO: Add a method to get all admin tokens for a clinic group (not just active ones)
|
|
5727
|
+
// TODO: Refactor admin token methods not to add tokens to the clinicGroup document,
|
|
5728
|
+
// but to add them to a subcollection called adminTokens that belongs to a specific clinicGroup document
|
|
5729
|
+
// TODO: Add granular control over admin permissions, e.g. only allow admins to manage certain clinics to tokens directly
|
|
5730
|
+
// TODO: Generally refactor admin tokens and invites, also create cloud function to send invites and send updates when sombody uses the token
|
|
5531
5731
|
};
|
|
5532
5732
|
|
|
5533
5733
|
// src/services/clinic/clinic.service.ts
|
|
@@ -5554,7 +5754,7 @@ async function getClinicsByGroup(db, groupId) {
|
|
|
5554
5754
|
(0, import_firestore18.where)("isActive", "==", true)
|
|
5555
5755
|
);
|
|
5556
5756
|
const querySnapshot = await (0, import_firestore18.getDocs)(q);
|
|
5557
|
-
return querySnapshot.docs.map((
|
|
5757
|
+
return querySnapshot.docs.map((doc33) => doc33.data());
|
|
5558
5758
|
}
|
|
5559
5759
|
async function updateClinic(db, clinicId, data, adminId, clinicAdminService, app) {
|
|
5560
5760
|
console.log("[CLINIC] Starting clinic update", { clinicId, adminId });
|
|
@@ -5748,7 +5948,7 @@ async function getClinicsByAdmin(db, adminId, options = {}, clinicAdminService,
|
|
|
5748
5948
|
}
|
|
5749
5949
|
const q = (0, import_firestore18.query)((0, import_firestore18.collection)(db, CLINICS_COLLECTION), ...constraints);
|
|
5750
5950
|
const querySnapshot = await (0, import_firestore18.getDocs)(q);
|
|
5751
|
-
return querySnapshot.docs.map((
|
|
5951
|
+
return querySnapshot.docs.map((doc33) => doc33.data());
|
|
5752
5952
|
}
|
|
5753
5953
|
async function getActiveClinicsByAdmin(db, adminId, clinicAdminService, clinicGroupService) {
|
|
5754
5954
|
return getClinicsByAdmin(
|
|
@@ -5793,11 +5993,11 @@ async function getAllClinics(db, pagination, lastDoc) {
|
|
|
5793
5993
|
}
|
|
5794
5994
|
const clinicsSnapshot = await (0, import_firestore18.getDocs)(clinicsQuery);
|
|
5795
5995
|
const lastVisible = clinicsSnapshot.docs[clinicsSnapshot.docs.length - 1];
|
|
5796
|
-
const clinics = clinicsSnapshot.docs.map((
|
|
5797
|
-
const data =
|
|
5996
|
+
const clinics = clinicsSnapshot.docs.map((doc33) => {
|
|
5997
|
+
const data = doc33.data();
|
|
5798
5998
|
return {
|
|
5799
5999
|
...data,
|
|
5800
|
-
id:
|
|
6000
|
+
id: doc33.id
|
|
5801
6001
|
};
|
|
5802
6002
|
});
|
|
5803
6003
|
return {
|
|
@@ -5824,8 +6024,8 @@ async function getAllClinicsInRange(db, center, rangeInKm, pagination, lastDoc)
|
|
|
5824
6024
|
];
|
|
5825
6025
|
const q = (0, import_firestore18.query)((0, import_firestore18.collection)(db, CLINICS_COLLECTION), ...constraints);
|
|
5826
6026
|
const querySnapshot = await (0, import_firestore18.getDocs)(q);
|
|
5827
|
-
for (const
|
|
5828
|
-
const clinic =
|
|
6027
|
+
for (const doc33 of querySnapshot.docs) {
|
|
6028
|
+
const clinic = doc33.data();
|
|
5829
6029
|
const distance = (0, import_geofire_common4.distanceBetween)(
|
|
5830
6030
|
[center.latitude, center.longitude],
|
|
5831
6031
|
[clinic.location.latitude, clinic.location.longitude]
|
|
@@ -5942,8 +6142,8 @@ async function findClinicsInRadius(db, center, radiusInKm, filters) {
|
|
|
5942
6142
|
}
|
|
5943
6143
|
const q = (0, import_firestore19.query)((0, import_firestore19.collection)(db, CLINICS_COLLECTION), ...constraints);
|
|
5944
6144
|
const querySnapshot = await (0, import_firestore19.getDocs)(q);
|
|
5945
|
-
for (const
|
|
5946
|
-
const clinic =
|
|
6145
|
+
for (const doc33 of querySnapshot.docs) {
|
|
6146
|
+
const clinic = doc33.data();
|
|
5947
6147
|
const distance = (0, import_geofire_common5.distanceBetween)(
|
|
5948
6148
|
[center.latitude, center.longitude],
|
|
5949
6149
|
[clinic.location.latitude, clinic.location.longitude]
|
|
@@ -6031,8 +6231,8 @@ async function getClinicsByFilters(db, filters) {
|
|
|
6031
6231
|
console.log(
|
|
6032
6232
|
`[FILTER_UTILS] Found ${querySnapshot.docs.length} clinics in geo bound`
|
|
6033
6233
|
);
|
|
6034
|
-
for (const
|
|
6035
|
-
const clinic = { ...
|
|
6234
|
+
for (const doc33 of querySnapshot.docs) {
|
|
6235
|
+
const clinic = { ...doc33.data(), id: doc33.id };
|
|
6036
6236
|
const distance = (0, import_geofire_common6.distanceBetween)(
|
|
6037
6237
|
[center.latitude, center.longitude],
|
|
6038
6238
|
[clinic.location.latitude, clinic.location.longitude]
|
|
@@ -6088,8 +6288,8 @@ async function getClinicsByFilters(db, filters) {
|
|
|
6088
6288
|
console.log(
|
|
6089
6289
|
`[FILTER_UTILS] Found ${querySnapshot.docs.length} clinics with regular query`
|
|
6090
6290
|
);
|
|
6091
|
-
const clinics = querySnapshot.docs.map((
|
|
6092
|
-
return { ...
|
|
6291
|
+
const clinics = querySnapshot.docs.map((doc33) => {
|
|
6292
|
+
return { ...doc33.data(), id: doc33.id };
|
|
6093
6293
|
});
|
|
6094
6294
|
let filteredClinics = clinics;
|
|
6095
6295
|
if (filters.center) {
|
|
@@ -7301,17 +7501,28 @@ var import_firestore23 = require("firebase/firestore");
|
|
|
7301
7501
|
|
|
7302
7502
|
// src/types/notifications/index.ts
|
|
7303
7503
|
var NotificationType = /* @__PURE__ */ ((NotificationType3) => {
|
|
7304
|
-
NotificationType3["PRE_REQUIREMENT"] = "preRequirement";
|
|
7305
|
-
NotificationType3["POST_REQUIREMENT"] = "postRequirement";
|
|
7306
7504
|
NotificationType3["APPOINTMENT_REMINDER"] = "appointmentReminder";
|
|
7307
|
-
NotificationType3["
|
|
7505
|
+
NotificationType3["APPOINTMENT_STATUS_CHANGE"] = "appointmentStatusChange";
|
|
7506
|
+
NotificationType3["APPOINTMENT_RESCHEDULED_PROPOSAL"] = "appointmentRescheduledProposal";
|
|
7507
|
+
NotificationType3["APPOINTMENT_CANCELLED"] = "appointmentCancelled";
|
|
7508
|
+
NotificationType3["REQUIREMENT_INSTRUCTION_DUE"] = "requirementInstructionDue";
|
|
7509
|
+
NotificationType3["FORM_REMINDER"] = "formReminder";
|
|
7510
|
+
NotificationType3["FORM_SUBMISSION_CONFIRMATION"] = "formSubmissionConfirmation";
|
|
7511
|
+
NotificationType3["REVIEW_REQUEST"] = "reviewRequest";
|
|
7512
|
+
NotificationType3["PAYMENT_DUE"] = "paymentDue";
|
|
7513
|
+
NotificationType3["PAYMENT_CONFIRMATION"] = "paymentConfirmation";
|
|
7514
|
+
NotificationType3["PAYMENT_FAILED"] = "paymentFailed";
|
|
7515
|
+
NotificationType3["GENERAL_MESSAGE"] = "generalMessage";
|
|
7516
|
+
NotificationType3["ACCOUNT_NOTIFICATION"] = "accountNotification";
|
|
7308
7517
|
return NotificationType3;
|
|
7309
7518
|
})(NotificationType || {});
|
|
7310
7519
|
var NOTIFICATIONS_COLLECTION = "notifications";
|
|
7311
7520
|
var NotificationStatus = /* @__PURE__ */ ((NotificationStatus2) => {
|
|
7312
7521
|
NotificationStatus2["PENDING"] = "pending";
|
|
7522
|
+
NotificationStatus2["PROCESSING"] = "processing";
|
|
7313
7523
|
NotificationStatus2["SENT"] = "sent";
|
|
7314
7524
|
NotificationStatus2["FAILED"] = "failed";
|
|
7525
|
+
NotificationStatus2["DELIVERED"] = "delivered";
|
|
7315
7526
|
NotificationStatus2["CANCELLED"] = "cancelled";
|
|
7316
7527
|
NotificationStatus2["PARTIAL_SUCCESS"] = "partialSuccess";
|
|
7317
7528
|
return NotificationStatus2;
|
|
@@ -7367,9 +7578,9 @@ var NotificationService = class extends BaseService {
|
|
|
7367
7578
|
(0, import_firestore23.orderBy)("notificationTime", "desc")
|
|
7368
7579
|
);
|
|
7369
7580
|
const querySnapshot = await (0, import_firestore23.getDocs)(q);
|
|
7370
|
-
return querySnapshot.docs.map((
|
|
7371
|
-
id:
|
|
7372
|
-
...
|
|
7581
|
+
return querySnapshot.docs.map((doc33) => ({
|
|
7582
|
+
id: doc33.id,
|
|
7583
|
+
...doc33.data()
|
|
7373
7584
|
}));
|
|
7374
7585
|
}
|
|
7375
7586
|
/**
|
|
@@ -7383,9 +7594,9 @@ var NotificationService = class extends BaseService {
|
|
|
7383
7594
|
(0, import_firestore23.orderBy)("notificationTime", "desc")
|
|
7384
7595
|
);
|
|
7385
7596
|
const querySnapshot = await (0, import_firestore23.getDocs)(q);
|
|
7386
|
-
return querySnapshot.docs.map((
|
|
7387
|
-
id:
|
|
7388
|
-
...
|
|
7597
|
+
return querySnapshot.docs.map((doc33) => ({
|
|
7598
|
+
id: doc33.id,
|
|
7599
|
+
...doc33.data()
|
|
7389
7600
|
}));
|
|
7390
7601
|
}
|
|
7391
7602
|
/**
|
|
@@ -7457,9 +7668,9 @@ var NotificationService = class extends BaseService {
|
|
|
7457
7668
|
(0, import_firestore23.orderBy)("notificationTime", "desc")
|
|
7458
7669
|
);
|
|
7459
7670
|
const querySnapshot = await (0, import_firestore23.getDocs)(q);
|
|
7460
|
-
return querySnapshot.docs.map((
|
|
7461
|
-
id:
|
|
7462
|
-
...
|
|
7671
|
+
return querySnapshot.docs.map((doc33) => ({
|
|
7672
|
+
id: doc33.id,
|
|
7673
|
+
...doc33.data()
|
|
7463
7674
|
}));
|
|
7464
7675
|
}
|
|
7465
7676
|
/**
|
|
@@ -7472,9 +7683,9 @@ var NotificationService = class extends BaseService {
|
|
|
7472
7683
|
(0, import_firestore23.orderBy)("notificationTime", "desc")
|
|
7473
7684
|
);
|
|
7474
7685
|
const querySnapshot = await (0, import_firestore23.getDocs)(q);
|
|
7475
|
-
return querySnapshot.docs.map((
|
|
7476
|
-
id:
|
|
7477
|
-
...
|
|
7686
|
+
return querySnapshot.docs.map((doc33) => ({
|
|
7687
|
+
id: doc33.id,
|
|
7688
|
+
...doc33.data()
|
|
7478
7689
|
}));
|
|
7479
7690
|
}
|
|
7480
7691
|
};
|
|
@@ -7691,7 +7902,7 @@ var ProcedureService = class extends BaseService {
|
|
|
7691
7902
|
(0, import_firestore24.where)("isActive", "==", true)
|
|
7692
7903
|
);
|
|
7693
7904
|
const snapshot = await (0, import_firestore24.getDocs)(q);
|
|
7694
|
-
return snapshot.docs.map((
|
|
7905
|
+
return snapshot.docs.map((doc33) => doc33.data());
|
|
7695
7906
|
}
|
|
7696
7907
|
/**
|
|
7697
7908
|
* Gets all procedures for a practitioner
|
|
@@ -7705,7 +7916,7 @@ var ProcedureService = class extends BaseService {
|
|
|
7705
7916
|
(0, import_firestore24.where)("isActive", "==", true)
|
|
7706
7917
|
);
|
|
7707
7918
|
const snapshot = await (0, import_firestore24.getDocs)(q);
|
|
7708
|
-
return snapshot.docs.map((
|
|
7919
|
+
return snapshot.docs.map((doc33) => doc33.data());
|
|
7709
7920
|
}
|
|
7710
7921
|
/**
|
|
7711
7922
|
* Updates a procedure
|
|
@@ -7888,20 +8099,20 @@ var ProcedureService = class extends BaseService {
|
|
|
7888
8099
|
const proceduresCollection = (0, import_firestore24.collection)(this.db, PROCEDURES_COLLECTION);
|
|
7889
8100
|
let proceduresQuery = (0, import_firestore24.query)(proceduresCollection);
|
|
7890
8101
|
if (pagination && pagination > 0) {
|
|
7891
|
-
const { limit:
|
|
8102
|
+
const { limit: limit12, startAfter: startAfter12 } = await import("firebase/firestore");
|
|
7892
8103
|
if (lastDoc) {
|
|
7893
8104
|
proceduresQuery = (0, import_firestore24.query)(
|
|
7894
8105
|
proceduresCollection,
|
|
7895
8106
|
(0, import_firestore24.orderBy)("name"),
|
|
7896
8107
|
// Use imported orderBy
|
|
7897
|
-
|
|
7898
|
-
|
|
8108
|
+
startAfter12(lastDoc),
|
|
8109
|
+
limit12(pagination)
|
|
7899
8110
|
);
|
|
7900
8111
|
} else {
|
|
7901
8112
|
proceduresQuery = (0, import_firestore24.query)(
|
|
7902
8113
|
proceduresCollection,
|
|
7903
8114
|
(0, import_firestore24.orderBy)("name"),
|
|
7904
|
-
|
|
8115
|
+
limit12(pagination)
|
|
7905
8116
|
);
|
|
7906
8117
|
}
|
|
7907
8118
|
} else {
|
|
@@ -7909,11 +8120,11 @@ var ProcedureService = class extends BaseService {
|
|
|
7909
8120
|
}
|
|
7910
8121
|
const proceduresSnapshot = await (0, import_firestore24.getDocs)(proceduresQuery);
|
|
7911
8122
|
const lastVisible = proceduresSnapshot.docs[proceduresSnapshot.docs.length - 1];
|
|
7912
|
-
const procedures = proceduresSnapshot.docs.map((
|
|
7913
|
-
const data =
|
|
8123
|
+
const procedures = proceduresSnapshot.docs.map((doc33) => {
|
|
8124
|
+
const data = doc33.data();
|
|
7914
8125
|
return {
|
|
7915
8126
|
...data,
|
|
7916
|
-
id:
|
|
8127
|
+
id: doc33.id
|
|
7917
8128
|
// Ensure ID is present
|
|
7918
8129
|
};
|
|
7919
8130
|
});
|
|
@@ -7995,8 +8206,8 @@ var ProcedureService = class extends BaseService {
|
|
|
7995
8206
|
console.log(
|
|
7996
8207
|
`[PROCEDURE_SERVICE] Found ${querySnapshot.docs.length} procedures in geo bound`
|
|
7997
8208
|
);
|
|
7998
|
-
for (const
|
|
7999
|
-
const procedure = { ...
|
|
8209
|
+
for (const doc33 of querySnapshot.docs) {
|
|
8210
|
+
const procedure = { ...doc33.data(), id: doc33.id };
|
|
8000
8211
|
const distance = (0, import_geofire_common8.distanceBetween)(
|
|
8001
8212
|
[center.latitude, center.longitude],
|
|
8002
8213
|
[
|
|
@@ -8047,8 +8258,8 @@ var ProcedureService = class extends BaseService {
|
|
|
8047
8258
|
console.log(
|
|
8048
8259
|
`[PROCEDURE_SERVICE] Found ${querySnapshot.docs.length} procedures with regular query`
|
|
8049
8260
|
);
|
|
8050
|
-
const procedures = querySnapshot.docs.map((
|
|
8051
|
-
return { ...
|
|
8261
|
+
const procedures = querySnapshot.docs.map((doc33) => {
|
|
8262
|
+
return { ...doc33.data(), id: doc33.id };
|
|
8052
8263
|
});
|
|
8053
8264
|
if (filters.location) {
|
|
8054
8265
|
const center = filters.location;
|
|
@@ -8188,7 +8399,10 @@ var DocumentationTemplateService = class extends BaseService {
|
|
|
8188
8399
|
createdBy: userId,
|
|
8189
8400
|
version: 1,
|
|
8190
8401
|
isActive: true,
|
|
8191
|
-
tags: validatedData.tags || []
|
|
8402
|
+
tags: validatedData.tags || [],
|
|
8403
|
+
isUserForm: validatedData.isUserForm || false,
|
|
8404
|
+
isRequired: validatedData.isRequired || false,
|
|
8405
|
+
sortingOrder: validatedData.sortingOrder || 0
|
|
8192
8406
|
};
|
|
8193
8407
|
const docRef = (0, import_firestore25.doc)(this.collectionRef, templateId);
|
|
8194
8408
|
await (0, import_firestore25.setDoc)(docRef, template);
|
|
@@ -8223,21 +8437,31 @@ var DocumentationTemplateService = class extends BaseService {
|
|
|
8223
8437
|
if (validatedData.elements) {
|
|
8224
8438
|
updatedElements = validatedData.elements.map((element) => ({
|
|
8225
8439
|
...element,
|
|
8226
|
-
id: this.generateId()
|
|
8440
|
+
id: element.id || this.generateId()
|
|
8227
8441
|
}));
|
|
8228
8442
|
}
|
|
8229
|
-
const
|
|
8230
|
-
...validatedData,
|
|
8443
|
+
const updatePayload = {
|
|
8231
8444
|
elements: updatedElements,
|
|
8232
8445
|
updatedAt: Date.now(),
|
|
8233
8446
|
version: template.version + 1
|
|
8234
8447
|
};
|
|
8448
|
+
if (validatedData.title !== void 0)
|
|
8449
|
+
updatePayload.title = validatedData.title;
|
|
8450
|
+
if (validatedData.description !== void 0)
|
|
8451
|
+
updatePayload.description = validatedData.description;
|
|
8452
|
+
if (validatedData.isActive !== void 0)
|
|
8453
|
+
updatePayload.isActive = validatedData.isActive;
|
|
8454
|
+
if (validatedData.tags !== void 0)
|
|
8455
|
+
updatePayload.tags = validatedData.tags;
|
|
8456
|
+
if (validatedData.isUserForm !== void 0)
|
|
8457
|
+
updatePayload.isUserForm = validatedData.isUserForm;
|
|
8458
|
+
if (validatedData.isRequired !== void 0)
|
|
8459
|
+
updatePayload.isRequired = validatedData.isRequired;
|
|
8460
|
+
if (validatedData.sortingOrder !== void 0)
|
|
8461
|
+
updatePayload.sortingOrder = validatedData.sortingOrder;
|
|
8235
8462
|
const docRef = (0, import_firestore25.doc)(this.collectionRef, templateId);
|
|
8236
|
-
await (0, import_firestore25.updateDoc)(docRef,
|
|
8237
|
-
return {
|
|
8238
|
-
...template,
|
|
8239
|
-
...updateData
|
|
8240
|
-
};
|
|
8463
|
+
await (0, import_firestore25.updateDoc)(docRef, updatePayload);
|
|
8464
|
+
return { ...template, ...updatePayload };
|
|
8241
8465
|
}
|
|
8242
8466
|
/**
|
|
8243
8467
|
* Delete a document template
|
|
@@ -8266,9 +8490,9 @@ var DocumentationTemplateService = class extends BaseService {
|
|
|
8266
8490
|
const querySnapshot = await (0, import_firestore25.getDocs)(q);
|
|
8267
8491
|
const templates = [];
|
|
8268
8492
|
let lastVisible = null;
|
|
8269
|
-
querySnapshot.forEach((
|
|
8270
|
-
templates.push(
|
|
8271
|
-
lastVisible =
|
|
8493
|
+
querySnapshot.forEach((doc33) => {
|
|
8494
|
+
templates.push(doc33.data());
|
|
8495
|
+
lastVisible = doc33;
|
|
8272
8496
|
});
|
|
8273
8497
|
return {
|
|
8274
8498
|
templates,
|
|
@@ -8296,9 +8520,9 @@ var DocumentationTemplateService = class extends BaseService {
|
|
|
8296
8520
|
const querySnapshot = await (0, import_firestore25.getDocs)(q);
|
|
8297
8521
|
const templates = [];
|
|
8298
8522
|
let lastVisible = null;
|
|
8299
|
-
querySnapshot.forEach((
|
|
8300
|
-
templates.push(
|
|
8301
|
-
lastVisible =
|
|
8523
|
+
querySnapshot.forEach((doc33) => {
|
|
8524
|
+
templates.push(doc33.data());
|
|
8525
|
+
lastVisible = doc33;
|
|
8302
8526
|
});
|
|
8303
8527
|
return {
|
|
8304
8528
|
templates,
|
|
@@ -8325,9 +8549,9 @@ var DocumentationTemplateService = class extends BaseService {
|
|
|
8325
8549
|
const querySnapshot = await (0, import_firestore25.getDocs)(q);
|
|
8326
8550
|
const templates = [];
|
|
8327
8551
|
let lastVisible = null;
|
|
8328
|
-
querySnapshot.forEach((
|
|
8329
|
-
templates.push(
|
|
8330
|
-
lastVisible =
|
|
8552
|
+
querySnapshot.forEach((doc33) => {
|
|
8553
|
+
templates.push(doc33.data());
|
|
8554
|
+
lastVisible = doc33;
|
|
8331
8555
|
});
|
|
8332
8556
|
return {
|
|
8333
8557
|
templates,
|
|
@@ -8341,50 +8565,80 @@ var import_firestore26 = require("firebase/firestore");
|
|
|
8341
8565
|
var FilledDocumentService = class extends BaseService {
|
|
8342
8566
|
constructor(...args) {
|
|
8343
8567
|
super(...args);
|
|
8344
|
-
this.collectionRef = (0, import_firestore26.collection)(
|
|
8345
|
-
this.db,
|
|
8346
|
-
FILLED_DOCUMENTS_COLLECTION
|
|
8347
|
-
);
|
|
8348
8568
|
this.templateService = new DocumentationTemplateService(...args);
|
|
8349
8569
|
}
|
|
8570
|
+
getFormSubcollectionPath(isUserForm) {
|
|
8571
|
+
return isUserForm ? USER_FORMS_SUBCOLLECTION : DOCTOR_FORMS_SUBCOLLECTION;
|
|
8572
|
+
}
|
|
8350
8573
|
/**
|
|
8351
|
-
* Create a new filled document
|
|
8352
|
-
* @param templateId - ID of the template to use
|
|
8353
|
-
* @param
|
|
8354
|
-
* @param
|
|
8355
|
-
* @param
|
|
8356
|
-
* @
|
|
8574
|
+
* Create a new filled document within an appointment's subcollection.
|
|
8575
|
+
* @param templateId - ID of the template to use.
|
|
8576
|
+
* @param appointmentId - ID of the appointment this form belongs to.
|
|
8577
|
+
* @param procedureId - ID of the procedure associated with this form.
|
|
8578
|
+
* @param patientId - ID of the patient.
|
|
8579
|
+
* @param practitionerId - ID of the practitioner (can be system/generic if patient is filling).
|
|
8580
|
+
* @param clinicId - ID of the clinic.
|
|
8581
|
+
* @param initialValues - Optional initial values for the form elements.
|
|
8582
|
+
* @param initialStatus - Optional initial status for the form.
|
|
8583
|
+
* @returns The created filled document.
|
|
8357
8584
|
*/
|
|
8358
|
-
async
|
|
8585
|
+
async createFilledDocumentForAppointment(templateId, appointmentId, procedureId, patientId, practitionerId, clinicId, initialValues = {}, initialStatus = "draft" /* DRAFT */) {
|
|
8359
8586
|
const template = await this.templateService.getTemplateById(templateId);
|
|
8360
8587
|
if (!template) {
|
|
8361
8588
|
throw new Error(`Template with ID ${templateId} not found`);
|
|
8362
8589
|
}
|
|
8363
8590
|
const documentId3 = this.generateId();
|
|
8364
8591
|
const now = Date.now();
|
|
8592
|
+
const isUserForm = template.isUserForm || false;
|
|
8593
|
+
const formSubcollection = this.getFormSubcollectionPath(isUserForm);
|
|
8365
8594
|
const filledDocument = {
|
|
8366
8595
|
id: documentId3,
|
|
8367
8596
|
templateId,
|
|
8368
8597
|
templateVersion: template.version,
|
|
8598
|
+
isUserForm,
|
|
8599
|
+
// Set based on template
|
|
8600
|
+
isRequired: template.isRequired || false,
|
|
8601
|
+
// Inherit isRequired from the template
|
|
8602
|
+
appointmentId,
|
|
8603
|
+
// NEW
|
|
8604
|
+
procedureId,
|
|
8605
|
+
// NEW
|
|
8369
8606
|
patientId,
|
|
8370
8607
|
practitionerId,
|
|
8371
8608
|
clinicId,
|
|
8372
8609
|
createdAt: now,
|
|
8373
8610
|
updatedAt: now,
|
|
8374
|
-
values:
|
|
8375
|
-
status:
|
|
8611
|
+
values: initialValues,
|
|
8612
|
+
status: initialStatus
|
|
8376
8613
|
};
|
|
8377
|
-
const docRef = (0, import_firestore26.doc)(
|
|
8614
|
+
const docRef = (0, import_firestore26.doc)(
|
|
8615
|
+
this.db,
|
|
8616
|
+
APPOINTMENTS_COLLECTION,
|
|
8617
|
+
// Replaced "appointments"
|
|
8618
|
+
appointmentId,
|
|
8619
|
+
formSubcollection,
|
|
8620
|
+
documentId3
|
|
8621
|
+
);
|
|
8378
8622
|
await (0, import_firestore26.setDoc)(docRef, filledDocument);
|
|
8379
8623
|
return filledDocument;
|
|
8380
8624
|
}
|
|
8381
8625
|
/**
|
|
8382
|
-
* Get a filled document
|
|
8383
|
-
* @param
|
|
8384
|
-
* @
|
|
8626
|
+
* Get a specific filled document from an appointment's subcollection.
|
|
8627
|
+
* @param appointmentId - ID of the appointment.
|
|
8628
|
+
* @param formId - ID of the filled document.
|
|
8629
|
+
* @param isUserForm - Boolean indicating if it's a user form or doctor form.
|
|
8630
|
+
* @returns The filled document or null if not found.
|
|
8385
8631
|
*/
|
|
8386
|
-
async
|
|
8387
|
-
const
|
|
8632
|
+
async getFilledDocumentFromAppointmentById(appointmentId, formId, isUserForm) {
|
|
8633
|
+
const formSubcollection = this.getFormSubcollectionPath(isUserForm);
|
|
8634
|
+
const docRef = (0, import_firestore26.doc)(
|
|
8635
|
+
this.db,
|
|
8636
|
+
APPOINTMENTS_COLLECTION,
|
|
8637
|
+
// Replaced "appointments"
|
|
8638
|
+
appointmentId,
|
|
8639
|
+
formSubcollection,
|
|
8640
|
+
formId
|
|
8641
|
+
);
|
|
8388
8642
|
const docSnap = await (0, import_firestore26.getDoc)(docRef);
|
|
8389
8643
|
if (!docSnap.exists()) {
|
|
8390
8644
|
return null;
|
|
@@ -8392,178 +8646,183 @@ var FilledDocumentService = class extends BaseService {
|
|
|
8392
8646
|
return docSnap.data();
|
|
8393
8647
|
}
|
|
8394
8648
|
/**
|
|
8395
|
-
* Update values in a filled document
|
|
8396
|
-
* @param
|
|
8397
|
-
* @param
|
|
8398
|
-
* @param
|
|
8399
|
-
* @
|
|
8649
|
+
* Update values or status in a filled document within an appointment's subcollection.
|
|
8650
|
+
* @param appointmentId - ID of the appointment.
|
|
8651
|
+
* @param formId - ID of the filled document to update.
|
|
8652
|
+
* @param isUserForm - Boolean indicating if it's a user form or doctor form.
|
|
8653
|
+
* @param values - Updated values for elements.
|
|
8654
|
+
* @param status - Optional new status for the document.
|
|
8655
|
+
* @returns The updated filled document.
|
|
8400
8656
|
*/
|
|
8401
|
-
async
|
|
8402
|
-
const
|
|
8403
|
-
|
|
8404
|
-
|
|
8657
|
+
async updateFilledDocumentInAppointment(appointmentId, formId, isUserForm, values, status) {
|
|
8658
|
+
const formSubcollection = this.getFormSubcollectionPath(isUserForm);
|
|
8659
|
+
const docRef = (0, import_firestore26.doc)(
|
|
8660
|
+
this.db,
|
|
8661
|
+
APPOINTMENTS_COLLECTION,
|
|
8662
|
+
// Replaced "appointments"
|
|
8663
|
+
appointmentId,
|
|
8664
|
+
formSubcollection,
|
|
8665
|
+
formId
|
|
8666
|
+
);
|
|
8667
|
+
const existingDoc = await this.getFilledDocumentFromAppointmentById(
|
|
8668
|
+
appointmentId,
|
|
8669
|
+
formId,
|
|
8670
|
+
isUserForm
|
|
8671
|
+
);
|
|
8672
|
+
if (!existingDoc) {
|
|
8673
|
+
throw new Error(
|
|
8674
|
+
`Filled document with ID ${formId} not found in appointment ${appointmentId} ${formSubcollection}`
|
|
8675
|
+
);
|
|
8405
8676
|
}
|
|
8406
|
-
const
|
|
8407
|
-
values: {
|
|
8408
|
-
...filledDocument.values,
|
|
8409
|
-
...values
|
|
8410
|
-
},
|
|
8677
|
+
const updatePayload = {
|
|
8411
8678
|
updatedAt: Date.now()
|
|
8412
8679
|
};
|
|
8680
|
+
if (values) {
|
|
8681
|
+
updatePayload.values = {
|
|
8682
|
+
...existingDoc.values,
|
|
8683
|
+
...values
|
|
8684
|
+
};
|
|
8685
|
+
}
|
|
8413
8686
|
if (status) {
|
|
8414
|
-
|
|
8687
|
+
updatePayload.status = status;
|
|
8415
8688
|
}
|
|
8416
|
-
|
|
8417
|
-
|
|
8418
|
-
|
|
8419
|
-
|
|
8420
|
-
...updateData
|
|
8421
|
-
};
|
|
8689
|
+
if (Object.keys(updatePayload).length === 1 && "updatedAt" in updatePayload) {
|
|
8690
|
+
}
|
|
8691
|
+
await (0, import_firestore26.updateDoc)(docRef, updatePayload);
|
|
8692
|
+
return { ...existingDoc, ...updatePayload };
|
|
8422
8693
|
}
|
|
8423
8694
|
/**
|
|
8424
|
-
* Get filled
|
|
8425
|
-
* @param
|
|
8426
|
-
* @param pageSize
|
|
8427
|
-
* @param lastDoc
|
|
8428
|
-
* @returns Array of filled documents and the last document for pagination
|
|
8695
|
+
* Get all filled user forms for a specific appointment.
|
|
8696
|
+
* @param appointmentId ID of the appointment.
|
|
8697
|
+
* @param pageSize Number of documents to retrieve.
|
|
8698
|
+
* @param lastDoc Last document from previous page for pagination.
|
|
8429
8699
|
*/
|
|
8430
|
-
async
|
|
8700
|
+
async getFilledUserFormsForAppointment(appointmentId, pageSize = 20, lastDoc) {
|
|
8701
|
+
const subcollectionRef = (0, import_firestore26.collection)(
|
|
8702
|
+
this.db,
|
|
8703
|
+
APPOINTMENTS_COLLECTION,
|
|
8704
|
+
// Replaced "appointments"
|
|
8705
|
+
appointmentId,
|
|
8706
|
+
USER_FORMS_SUBCOLLECTION
|
|
8707
|
+
);
|
|
8431
8708
|
let q = (0, import_firestore26.query)(
|
|
8432
|
-
|
|
8433
|
-
(0, import_firestore26.where)("patientId", "==", patientId),
|
|
8709
|
+
subcollectionRef,
|
|
8434
8710
|
(0, import_firestore26.orderBy)("updatedAt", "desc"),
|
|
8435
8711
|
(0, import_firestore26.limit)(pageSize)
|
|
8436
8712
|
);
|
|
8437
8713
|
if (lastDoc) {
|
|
8438
8714
|
q = (0, import_firestore26.query)(q, (0, import_firestore26.startAfter)(lastDoc));
|
|
8439
8715
|
}
|
|
8440
|
-
|
|
8441
|
-
const documents = [];
|
|
8442
|
-
let lastVisible = null;
|
|
8443
|
-
querySnapshot.forEach((doc32) => {
|
|
8444
|
-
documents.push(doc32.data());
|
|
8445
|
-
lastVisible = doc32;
|
|
8446
|
-
});
|
|
8447
|
-
return {
|
|
8448
|
-
documents,
|
|
8449
|
-
lastDoc: lastVisible
|
|
8450
|
-
};
|
|
8716
|
+
return this.executeQuery(q);
|
|
8451
8717
|
}
|
|
8452
8718
|
/**
|
|
8453
|
-
* Get filled
|
|
8454
|
-
* @param
|
|
8455
|
-
* @param pageSize
|
|
8456
|
-
* @param lastDoc
|
|
8457
|
-
* @returns Array of filled documents and the last document for pagination
|
|
8719
|
+
* Get all filled doctor forms for a specific appointment.
|
|
8720
|
+
* @param appointmentId ID of the appointment.
|
|
8721
|
+
* @param pageSize Number of documents to retrieve.
|
|
8722
|
+
* @param lastDoc Last document from previous page for pagination.
|
|
8458
8723
|
*/
|
|
8459
|
-
async
|
|
8724
|
+
async getFilledDoctorFormsForAppointment(appointmentId, pageSize = 20, lastDoc) {
|
|
8725
|
+
const subcollectionRef = (0, import_firestore26.collection)(
|
|
8726
|
+
this.db,
|
|
8727
|
+
APPOINTMENTS_COLLECTION,
|
|
8728
|
+
// Replaced "appointments"
|
|
8729
|
+
appointmentId,
|
|
8730
|
+
DOCTOR_FORMS_SUBCOLLECTION
|
|
8731
|
+
);
|
|
8460
8732
|
let q = (0, import_firestore26.query)(
|
|
8461
|
-
|
|
8462
|
-
(0, import_firestore26.where)("practitionerId", "==", practitionerId),
|
|
8733
|
+
subcollectionRef,
|
|
8463
8734
|
(0, import_firestore26.orderBy)("updatedAt", "desc"),
|
|
8464
8735
|
(0, import_firestore26.limit)(pageSize)
|
|
8465
8736
|
);
|
|
8466
8737
|
if (lastDoc) {
|
|
8467
8738
|
q = (0, import_firestore26.query)(q, (0, import_firestore26.startAfter)(lastDoc));
|
|
8468
8739
|
}
|
|
8740
|
+
return this.executeQuery(q);
|
|
8741
|
+
}
|
|
8742
|
+
// Helper to execute query and return documents + lastDoc
|
|
8743
|
+
async executeQuery(q) {
|
|
8469
8744
|
const querySnapshot = await (0, import_firestore26.getDocs)(q);
|
|
8470
8745
|
const documents = [];
|
|
8471
8746
|
let lastVisible = null;
|
|
8472
|
-
querySnapshot.forEach((
|
|
8473
|
-
documents.push(
|
|
8474
|
-
lastVisible =
|
|
8747
|
+
querySnapshot.forEach((doc33) => {
|
|
8748
|
+
documents.push(doc33.data());
|
|
8749
|
+
lastVisible = doc33;
|
|
8475
8750
|
});
|
|
8476
8751
|
return {
|
|
8477
8752
|
documents,
|
|
8478
8753
|
lastDoc: lastVisible
|
|
8479
8754
|
};
|
|
8480
8755
|
}
|
|
8756
|
+
// IMPORTANT: The following methods that query across all patients/practitioners/clinics
|
|
8757
|
+
// (e.g., getFilledDocumentsByPatient, getFilledDocumentsByPractitioner)
|
|
8758
|
+
// will NOT work correctly if FILLED_DOCUMENTS_COLLECTION is no longer a top-level collection
|
|
8759
|
+
// and data is only in appointment subcollections. You would need to use
|
|
8760
|
+
// Firestore Collection Group Queries for that, which require an index and a different query approach.
|
|
8761
|
+
// These methods are left here for now but would need significant rework or removal.
|
|
8762
|
+
/**
|
|
8763
|
+
* Get filled documents for a patient (NEEDS REWORK for subcollections or Collection Group Query)
|
|
8764
|
+
* @param patientId - ID of the patient
|
|
8765
|
+
* @param pageSize - Number of documents to retrieve
|
|
8766
|
+
* @param lastDoc - Last document from previous page for pagination
|
|
8767
|
+
* @returns Array of filled documents and the last document for pagination
|
|
8768
|
+
*/
|
|
8769
|
+
async getFilledDocumentsByPatient(patientId, pageSize = 20, lastDoc) {
|
|
8770
|
+
console.warn(
|
|
8771
|
+
"getFilledDocumentsByPatient needs rework for subcollection model or Collection Group Queries."
|
|
8772
|
+
);
|
|
8773
|
+
return { documents: [], lastDoc: null };
|
|
8774
|
+
}
|
|
8481
8775
|
/**
|
|
8482
|
-
* Get filled documents for a
|
|
8776
|
+
* Get filled documents for a practitioner (NEEDS REWORK for subcollections or Collection Group Query)
|
|
8777
|
+
* @param practitionerId - ID of the practitioner
|
|
8778
|
+
* @param pageSize - Number of documents to retrieve
|
|
8779
|
+
* @param lastDoc - Last document from previous page for pagination
|
|
8780
|
+
* @returns Array of filled documents and the last document for pagination
|
|
8781
|
+
*/
|
|
8782
|
+
async getFilledDocumentsByPractitioner(practitionerId, pageSize = 20, lastDoc) {
|
|
8783
|
+
console.warn(
|
|
8784
|
+
"getFilledDocumentsByPractitioner needs rework for subcollection model or Collection Group Queries."
|
|
8785
|
+
);
|
|
8786
|
+
return { documents: [], lastDoc: null };
|
|
8787
|
+
}
|
|
8788
|
+
/**
|
|
8789
|
+
* Get filled documents for a clinic (NEEDS REWORK for subcollections or Collection Group Query)
|
|
8483
8790
|
* @param clinicId - ID of the clinic
|
|
8484
8791
|
* @param pageSize - Number of documents to retrieve
|
|
8485
8792
|
* @param lastDoc - Last document from previous page for pagination
|
|
8486
8793
|
* @returns Array of filled documents and the last document for pagination
|
|
8487
8794
|
*/
|
|
8488
8795
|
async getFilledDocumentsByClinic(clinicId, pageSize = 20, lastDoc) {
|
|
8489
|
-
|
|
8490
|
-
|
|
8491
|
-
(0, import_firestore26.where)("clinicId", "==", clinicId),
|
|
8492
|
-
(0, import_firestore26.orderBy)("updatedAt", "desc"),
|
|
8493
|
-
(0, import_firestore26.limit)(pageSize)
|
|
8796
|
+
console.warn(
|
|
8797
|
+
"getFilledDocumentsByClinic needs rework for subcollection model or Collection Group Queries."
|
|
8494
8798
|
);
|
|
8495
|
-
|
|
8496
|
-
q = (0, import_firestore26.query)(q, (0, import_firestore26.startAfter)(lastDoc));
|
|
8497
|
-
}
|
|
8498
|
-
const querySnapshot = await (0, import_firestore26.getDocs)(q);
|
|
8499
|
-
const documents = [];
|
|
8500
|
-
let lastVisible = null;
|
|
8501
|
-
querySnapshot.forEach((doc32) => {
|
|
8502
|
-
documents.push(doc32.data());
|
|
8503
|
-
lastVisible = doc32;
|
|
8504
|
-
});
|
|
8505
|
-
return {
|
|
8506
|
-
documents,
|
|
8507
|
-
lastDoc: lastVisible
|
|
8508
|
-
};
|
|
8799
|
+
return { documents: [], lastDoc: null };
|
|
8509
8800
|
}
|
|
8510
8801
|
/**
|
|
8511
|
-
* Get filled documents by template
|
|
8802
|
+
* Get filled documents by template (NEEDS REWORK for subcollections or Collection Group Query)
|
|
8512
8803
|
* @param templateId - ID of the template
|
|
8513
8804
|
* @param pageSize - Number of documents to retrieve
|
|
8514
8805
|
* @param lastDoc - Last document from previous page for pagination
|
|
8515
8806
|
* @returns Array of filled documents and the last document for pagination
|
|
8516
8807
|
*/
|
|
8517
8808
|
async getFilledDocumentsByTemplate(templateId, pageSize = 20, lastDoc) {
|
|
8518
|
-
|
|
8519
|
-
|
|
8520
|
-
(0, import_firestore26.where)("templateId", "==", templateId),
|
|
8521
|
-
(0, import_firestore26.orderBy)("updatedAt", "desc"),
|
|
8522
|
-
(0, import_firestore26.limit)(pageSize)
|
|
8809
|
+
console.warn(
|
|
8810
|
+
"getFilledDocumentsByTemplate needs rework for subcollection model or Collection Group Queries."
|
|
8523
8811
|
);
|
|
8524
|
-
|
|
8525
|
-
q = (0, import_firestore26.query)(q, (0, import_firestore26.startAfter)(lastDoc));
|
|
8526
|
-
}
|
|
8527
|
-
const querySnapshot = await (0, import_firestore26.getDocs)(q);
|
|
8528
|
-
const documents = [];
|
|
8529
|
-
let lastVisible = null;
|
|
8530
|
-
querySnapshot.forEach((doc32) => {
|
|
8531
|
-
documents.push(doc32.data());
|
|
8532
|
-
lastVisible = doc32;
|
|
8533
|
-
});
|
|
8534
|
-
return {
|
|
8535
|
-
documents,
|
|
8536
|
-
lastDoc: lastVisible
|
|
8537
|
-
};
|
|
8812
|
+
return { documents: [], lastDoc: null };
|
|
8538
8813
|
}
|
|
8539
8814
|
/**
|
|
8540
|
-
* Get filled documents by status
|
|
8815
|
+
* Get filled documents by status (NEEDS REWORK for subcollections or Collection Group Query)
|
|
8541
8816
|
* @param status - Status to filter by
|
|
8542
8817
|
* @param pageSize - Number of documents to retrieve
|
|
8543
8818
|
* @param lastDoc - Last document from previous page for pagination
|
|
8544
8819
|
* @returns Array of filled documents and the last document for pagination
|
|
8545
8820
|
*/
|
|
8546
8821
|
async getFilledDocumentsByStatus(status, pageSize = 20, lastDoc) {
|
|
8547
|
-
|
|
8548
|
-
|
|
8549
|
-
(0, import_firestore26.where)("status", "==", status),
|
|
8550
|
-
(0, import_firestore26.orderBy)("updatedAt", "desc"),
|
|
8551
|
-
(0, import_firestore26.limit)(pageSize)
|
|
8822
|
+
console.warn(
|
|
8823
|
+
"getFilledDocumentsByStatus needs rework for subcollection model or Collection Group Queries."
|
|
8552
8824
|
);
|
|
8553
|
-
|
|
8554
|
-
q = (0, import_firestore26.query)(q, (0, import_firestore26.startAfter)(lastDoc));
|
|
8555
|
-
}
|
|
8556
|
-
const querySnapshot = await (0, import_firestore26.getDocs)(q);
|
|
8557
|
-
const documents = [];
|
|
8558
|
-
let lastVisible = null;
|
|
8559
|
-
querySnapshot.forEach((doc32) => {
|
|
8560
|
-
documents.push(doc32.data());
|
|
8561
|
-
lastVisible = doc32;
|
|
8562
|
-
});
|
|
8563
|
-
return {
|
|
8564
|
-
documents,
|
|
8565
|
-
lastDoc: lastVisible
|
|
8566
|
-
};
|
|
8825
|
+
return { documents: [], lastDoc: null };
|
|
8567
8826
|
}
|
|
8568
8827
|
};
|
|
8569
8828
|
|
|
@@ -9055,7 +9314,7 @@ async function searchCalendarEventsUtil(db, params) {
|
|
|
9055
9314
|
const finalQuery = (0, import_firestore33.query)(collectionRef, ...constraints);
|
|
9056
9315
|
const querySnapshot = await (0, import_firestore33.getDocs)(finalQuery);
|
|
9057
9316
|
const events = querySnapshot.docs.map(
|
|
9058
|
-
(
|
|
9317
|
+
(doc33) => ({ id: doc33.id, ...doc33.data() })
|
|
9059
9318
|
);
|
|
9060
9319
|
return events;
|
|
9061
9320
|
} catch (error) {
|
|
@@ -9137,7 +9396,7 @@ async function getPractitionerSyncedCalendarsUtil(db, practitionerId) {
|
|
|
9137
9396
|
);
|
|
9138
9397
|
const q = (0, import_firestore34.query)(calendarsRef, (0, import_firestore34.orderBy)("createdAt", "desc"));
|
|
9139
9398
|
const querySnapshot = await (0, import_firestore34.getDocs)(q);
|
|
9140
|
-
return querySnapshot.docs.map((
|
|
9399
|
+
return querySnapshot.docs.map((doc33) => doc33.data());
|
|
9141
9400
|
}
|
|
9142
9401
|
async function getPatientSyncedCalendarUtil(db, patientId, calendarId) {
|
|
9143
9402
|
const calendarRef = getPatientSyncedCalendarDocRef(db, patientId, calendarId);
|
|
@@ -9154,7 +9413,7 @@ async function getPatientSyncedCalendarsUtil(db, patientId) {
|
|
|
9154
9413
|
);
|
|
9155
9414
|
const q = (0, import_firestore34.query)(calendarsRef, (0, import_firestore34.orderBy)("createdAt", "desc"));
|
|
9156
9415
|
const querySnapshot = await (0, import_firestore34.getDocs)(q);
|
|
9157
|
-
return querySnapshot.docs.map((
|
|
9416
|
+
return querySnapshot.docs.map((doc33) => doc33.data());
|
|
9158
9417
|
}
|
|
9159
9418
|
async function getClinicSyncedCalendarUtil(db, clinicId, calendarId) {
|
|
9160
9419
|
const calendarRef = getClinicSyncedCalendarDocRef(db, clinicId, calendarId);
|
|
@@ -9171,7 +9430,7 @@ async function getClinicSyncedCalendarsUtil(db, clinicId) {
|
|
|
9171
9430
|
);
|
|
9172
9431
|
const q = (0, import_firestore34.query)(calendarsRef, (0, import_firestore34.orderBy)("createdAt", "desc"));
|
|
9173
9432
|
const querySnapshot = await (0, import_firestore34.getDocs)(q);
|
|
9174
|
-
return querySnapshot.docs.map((
|
|
9433
|
+
return querySnapshot.docs.map((doc33) => doc33.data());
|
|
9175
9434
|
}
|
|
9176
9435
|
async function updatePractitionerSyncedCalendarUtil(db, practitionerId, calendarId, updateData) {
|
|
9177
9436
|
const calendarRef = getPractitionerSyncedCalendarDocRef(
|
|
@@ -10526,9 +10785,9 @@ var CalendarServiceV2 = class extends BaseService {
|
|
|
10526
10785
|
(0, import_firestore37.where)("eventTime.start", "<=", import_firestore36.Timestamp.fromDate(endDate))
|
|
10527
10786
|
);
|
|
10528
10787
|
const eventsSnapshot = await (0, import_firestore37.getDocs)(q);
|
|
10529
|
-
const events = eventsSnapshot.docs.map((
|
|
10530
|
-
id:
|
|
10531
|
-
...
|
|
10788
|
+
const events = eventsSnapshot.docs.map((doc33) => ({
|
|
10789
|
+
id: doc33.id,
|
|
10790
|
+
...doc33.data()
|
|
10532
10791
|
}));
|
|
10533
10792
|
const calendars = await this.syncedCalendarsService.getPractitionerSyncedCalendars(
|
|
10534
10793
|
doctorId
|
|
@@ -11160,7 +11419,7 @@ var CalendarServiceV2 = class extends BaseService {
|
|
|
11160
11419
|
])
|
|
11161
11420
|
);
|
|
11162
11421
|
const querySnapshot = await (0, import_firestore37.getDocs)(q);
|
|
11163
|
-
return querySnapshot.docs.map((
|
|
11422
|
+
return querySnapshot.docs.map((doc33) => doc33.data());
|
|
11164
11423
|
}
|
|
11165
11424
|
/**
|
|
11166
11425
|
* Calculates available time slots based on working hours, schedule and existing appointments
|
|
@@ -11427,7 +11686,7 @@ var ReviewService = class extends BaseService {
|
|
|
11427
11686
|
(0, import_firestore38.where)("patientId", "==", patientId)
|
|
11428
11687
|
);
|
|
11429
11688
|
const snapshot = await (0, import_firestore38.getDocs)(q);
|
|
11430
|
-
return snapshot.docs.map((
|
|
11689
|
+
return snapshot.docs.map((doc33) => doc33.data());
|
|
11431
11690
|
}
|
|
11432
11691
|
/**
|
|
11433
11692
|
* Gets all reviews for a specific clinic
|
|
@@ -11440,7 +11699,7 @@ var ReviewService = class extends BaseService {
|
|
|
11440
11699
|
(0, import_firestore38.where)("clinicReview.clinicId", "==", clinicId)
|
|
11441
11700
|
);
|
|
11442
11701
|
const snapshot = await (0, import_firestore38.getDocs)(q);
|
|
11443
|
-
return snapshot.docs.map((
|
|
11702
|
+
return snapshot.docs.map((doc33) => doc33.data());
|
|
11444
11703
|
}
|
|
11445
11704
|
/**
|
|
11446
11705
|
* Gets all reviews for a specific practitioner
|
|
@@ -11453,7 +11712,7 @@ var ReviewService = class extends BaseService {
|
|
|
11453
11712
|
(0, import_firestore38.where)("practitionerReview.practitionerId", "==", practitionerId)
|
|
11454
11713
|
);
|
|
11455
11714
|
const snapshot = await (0, import_firestore38.getDocs)(q);
|
|
11456
|
-
return snapshot.docs.map((
|
|
11715
|
+
return snapshot.docs.map((doc33) => doc33.data());
|
|
11457
11716
|
}
|
|
11458
11717
|
/**
|
|
11459
11718
|
* Gets all reviews for a specific procedure
|
|
@@ -11466,7 +11725,7 @@ var ReviewService = class extends BaseService {
|
|
|
11466
11725
|
(0, import_firestore38.where)("procedureReview.procedureId", "==", procedureId)
|
|
11467
11726
|
);
|
|
11468
11727
|
const snapshot = await (0, import_firestore38.getDocs)(q);
|
|
11469
|
-
return snapshot.docs.map((
|
|
11728
|
+
return snapshot.docs.map((doc33) => doc33.data());
|
|
11470
11729
|
}
|
|
11471
11730
|
/**
|
|
11472
11731
|
* Gets all reviews for a specific appointment
|
|
@@ -12165,7 +12424,7 @@ async function updateCalendarEventStatus(db, calendarEventId, appointmentStatus)
|
|
|
12165
12424
|
case "canceled_clinic" /* CANCELED_CLINIC */:
|
|
12166
12425
|
calendarStatus = "canceled";
|
|
12167
12426
|
break;
|
|
12168
|
-
case
|
|
12427
|
+
case AppointmentStatus.RESCHEDULED:
|
|
12169
12428
|
calendarStatus = "rescheduled";
|
|
12170
12429
|
break;
|
|
12171
12430
|
case "completed" /* COMPLETED */:
|
|
@@ -12239,7 +12498,7 @@ async function searchAppointmentsUtil(db, params) {
|
|
|
12239
12498
|
const q = (0, import_firestore39.query)((0, import_firestore39.collection)(db, APPOINTMENTS_COLLECTION), ...constraints);
|
|
12240
12499
|
const querySnapshot = await (0, import_firestore39.getDocs)(q);
|
|
12241
12500
|
const appointments = querySnapshot.docs.map(
|
|
12242
|
-
(
|
|
12501
|
+
(doc33) => doc33.data()
|
|
12243
12502
|
);
|
|
12244
12503
|
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
12245
12504
|
return { appointments, lastDoc };
|
|
@@ -12262,12 +12521,13 @@ var AppointmentService = class extends BaseService {
|
|
|
12262
12521
|
* @param practitionerService Practitioner service instance
|
|
12263
12522
|
* @param clinicService Clinic service instance
|
|
12264
12523
|
*/
|
|
12265
|
-
constructor(db, auth, app, calendarService, patientService, practitionerService, clinicService) {
|
|
12524
|
+
constructor(db, auth, app, calendarService, patientService, practitionerService, clinicService, filledDocumentService) {
|
|
12266
12525
|
super(db, auth, app);
|
|
12267
12526
|
this.calendarService = calendarService;
|
|
12268
12527
|
this.patientService = patientService;
|
|
12269
12528
|
this.practitionerService = practitionerService;
|
|
12270
12529
|
this.clinicService = clinicService;
|
|
12530
|
+
this.filledDocumentService = filledDocumentService;
|
|
12271
12531
|
this.functions = (0, import_functions.getFunctions)(app, "europe-west6");
|
|
12272
12532
|
}
|
|
12273
12533
|
/**
|
|
@@ -12623,152 +12883,331 @@ var AppointmentService = class extends BaseService {
|
|
|
12623
12883
|
*
|
|
12624
12884
|
* @param appointmentId ID of the appointment
|
|
12625
12885
|
* @param newStatus New status to set
|
|
12626
|
-
* @param
|
|
12627
|
-
* @param canceledBy Required if canceling the appointment
|
|
12886
|
+
* @param details Optional details for the status change
|
|
12628
12887
|
* @returns The updated appointment
|
|
12629
12888
|
*/
|
|
12630
|
-
async updateAppointmentStatus(appointmentId, newStatus,
|
|
12889
|
+
async updateAppointmentStatus(appointmentId, newStatus, details) {
|
|
12631
12890
|
console.log(
|
|
12632
12891
|
`[APPOINTMENT_SERVICE] Updating status of appointment ${appointmentId} to ${newStatus}`
|
|
12633
12892
|
);
|
|
12634
|
-
const updateData = {
|
|
12635
|
-
|
|
12636
|
-
|
|
12637
|
-
|
|
12638
|
-
|
|
12639
|
-
|
|
12893
|
+
const updateData = {
|
|
12894
|
+
status: newStatus,
|
|
12895
|
+
updatedAt: (0, import_firestore40.serverTimestamp)()
|
|
12896
|
+
};
|
|
12897
|
+
if (newStatus === "canceled_clinic" /* CANCELED_CLINIC */ || newStatus === "canceled_patient" /* CANCELED_PATIENT */ || newStatus === "canceled_patient_rescheduled" /* CANCELED_PATIENT_RESCHEDULED */) {
|
|
12898
|
+
if (!(details == null ? void 0 : details.cancellationReason)) {
|
|
12899
|
+
throw new Error("Cancellation reason is required when canceling.");
|
|
12640
12900
|
}
|
|
12641
|
-
if (!canceledBy) {
|
|
12642
|
-
throw new Error(
|
|
12643
|
-
"Canceled by is required when canceling an appointment"
|
|
12644
|
-
);
|
|
12901
|
+
if (!(details == null ? void 0 : details.canceledBy)) {
|
|
12902
|
+
throw new Error("Canceled by is required when canceling.");
|
|
12645
12903
|
}
|
|
12646
|
-
updateData.cancellationReason = cancellationReason;
|
|
12647
|
-
updateData.canceledBy = canceledBy;
|
|
12904
|
+
updateData.cancellationReason = details.cancellationReason;
|
|
12905
|
+
updateData.canceledBy = details.canceledBy;
|
|
12906
|
+
updateData.cancellationTime = import_firestore40.Timestamp.now();
|
|
12648
12907
|
}
|
|
12649
12908
|
if (newStatus === "confirmed" /* CONFIRMED */) {
|
|
12650
12909
|
updateData.confirmationTime = import_firestore40.Timestamp.now();
|
|
12651
12910
|
}
|
|
12911
|
+
if (newStatus === "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */) {
|
|
12912
|
+
updateData.rescheduleTime = import_firestore40.Timestamp.now();
|
|
12913
|
+
}
|
|
12652
12914
|
return this.updateAppointment(appointmentId, updateData);
|
|
12653
12915
|
}
|
|
12654
12916
|
/**
|
|
12655
|
-
* Confirms an
|
|
12656
|
-
*
|
|
12657
|
-
* @param appointmentId ID of the appointment to confirm
|
|
12658
|
-
* @returns The confirmed appointment
|
|
12917
|
+
* Confirms a PENDING appointment by an Admin/Clinic.
|
|
12659
12918
|
*/
|
|
12660
|
-
async
|
|
12919
|
+
async confirmAppointmentAdmin(appointmentId) {
|
|
12661
12920
|
console.log(
|
|
12662
|
-
`[APPOINTMENT_SERVICE]
|
|
12921
|
+
`[APPOINTMENT_SERVICE] Admin confirming appointment: ${appointmentId}`
|
|
12663
12922
|
);
|
|
12923
|
+
const appointment = await this.getAppointmentById(appointmentId);
|
|
12924
|
+
if (!appointment)
|
|
12925
|
+
throw new Error(`Appointment ${appointmentId} not found.`);
|
|
12926
|
+
if (appointment.status !== "pending" /* PENDING */) {
|
|
12927
|
+
throw new Error(
|
|
12928
|
+
`Appointment ${appointmentId} is not in PENDING state to be confirmed.`
|
|
12929
|
+
);
|
|
12930
|
+
}
|
|
12664
12931
|
return this.updateAppointmentStatus(
|
|
12665
12932
|
appointmentId,
|
|
12666
12933
|
"confirmed" /* CONFIRMED */
|
|
12667
12934
|
);
|
|
12668
12935
|
}
|
|
12669
12936
|
/**
|
|
12670
|
-
* Cancels an appointment
|
|
12671
|
-
|
|
12672
|
-
|
|
12673
|
-
|
|
12674
|
-
|
|
12937
|
+
* Cancels an appointment by the User (Patient).
|
|
12938
|
+
*/
|
|
12939
|
+
async cancelAppointmentUser(appointmentId, reason) {
|
|
12940
|
+
console.log(
|
|
12941
|
+
`[APPOINTMENT_SERVICE] User canceling appointment: ${appointmentId}`
|
|
12942
|
+
);
|
|
12943
|
+
return this.updateAppointmentStatus(
|
|
12944
|
+
appointmentId,
|
|
12945
|
+
"canceled_patient" /* CANCELED_PATIENT */,
|
|
12946
|
+
{
|
|
12947
|
+
cancellationReason: reason,
|
|
12948
|
+
canceledBy: "patient"
|
|
12949
|
+
}
|
|
12950
|
+
);
|
|
12951
|
+
}
|
|
12952
|
+
/**
|
|
12953
|
+
* Cancels an appointment by an Admin/Clinic.
|
|
12675
12954
|
*/
|
|
12676
|
-
async
|
|
12955
|
+
async cancelAppointmentAdmin(appointmentId, reason) {
|
|
12677
12956
|
console.log(
|
|
12678
|
-
`[APPOINTMENT_SERVICE]
|
|
12957
|
+
`[APPOINTMENT_SERVICE] Admin canceling appointment: ${appointmentId}`
|
|
12679
12958
|
);
|
|
12680
12959
|
return this.updateAppointmentStatus(
|
|
12681
12960
|
appointmentId,
|
|
12682
12961
|
"canceled_clinic" /* CANCELED_CLINIC */,
|
|
12683
|
-
|
|
12684
|
-
|
|
12962
|
+
{
|
|
12963
|
+
cancellationReason: reason,
|
|
12964
|
+
canceledBy: "clinic"
|
|
12965
|
+
}
|
|
12685
12966
|
);
|
|
12686
12967
|
}
|
|
12687
12968
|
/**
|
|
12688
|
-
*
|
|
12689
|
-
*
|
|
12690
|
-
|
|
12691
|
-
|
|
12692
|
-
|
|
12969
|
+
* Admin proposes to reschedule an appointment.
|
|
12970
|
+
* Sets status to RESCHEDULED_BY_CLINIC and updates times.
|
|
12971
|
+
*/
|
|
12972
|
+
async rescheduleAppointmentAdmin(appointmentId, newStartTime, newEndTime) {
|
|
12973
|
+
console.log(
|
|
12974
|
+
`[APPOINTMENT_SERVICE] Admin rescheduling appointment: ${appointmentId}`
|
|
12975
|
+
);
|
|
12976
|
+
if (newEndTime.toMillis() <= newStartTime.toMillis()) {
|
|
12977
|
+
throw new Error("New end time must be after new start time.");
|
|
12978
|
+
}
|
|
12979
|
+
const updateData = {
|
|
12980
|
+
status: "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */,
|
|
12981
|
+
appointmentStartTime: newStartTime,
|
|
12982
|
+
appointmentEndTime: newEndTime,
|
|
12983
|
+
rescheduleTime: import_firestore40.Timestamp.now(),
|
|
12984
|
+
confirmationTime: null,
|
|
12985
|
+
updatedAt: (0, import_firestore40.serverTimestamp)()
|
|
12986
|
+
};
|
|
12987
|
+
return this.updateAppointment(appointmentId, updateData);
|
|
12988
|
+
}
|
|
12989
|
+
/**
|
|
12990
|
+
* User confirms a reschedule proposed by the clinic.
|
|
12991
|
+
* Status changes from RESCHEDULED_BY_CLINIC to CONFIRMED.
|
|
12693
12992
|
*/
|
|
12694
|
-
async
|
|
12993
|
+
async rescheduleAppointmentConfirmUser(appointmentId) {
|
|
12695
12994
|
console.log(
|
|
12696
|
-
`[APPOINTMENT_SERVICE]
|
|
12995
|
+
`[APPOINTMENT_SERVICE] User confirming reschedule for: ${appointmentId}`
|
|
12697
12996
|
);
|
|
12997
|
+
const appointment = await this.getAppointmentById(appointmentId);
|
|
12998
|
+
if (!appointment)
|
|
12999
|
+
throw new Error(`Appointment ${appointmentId} not found.`);
|
|
13000
|
+
if (appointment.status !== "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */) {
|
|
13001
|
+
throw new Error(
|
|
13002
|
+
`Appointment ${appointmentId} is not in RESCHEDULED_BY_CLINIC state.`
|
|
13003
|
+
);
|
|
13004
|
+
}
|
|
12698
13005
|
return this.updateAppointmentStatus(
|
|
12699
13006
|
appointmentId,
|
|
12700
|
-
"
|
|
12701
|
-
reason,
|
|
12702
|
-
"patient"
|
|
13007
|
+
"confirmed" /* CONFIRMED */
|
|
12703
13008
|
);
|
|
12704
13009
|
}
|
|
12705
13010
|
/**
|
|
12706
|
-
*
|
|
12707
|
-
*
|
|
12708
|
-
* @param appointmentId ID of the appointment
|
|
12709
|
-
* @returns The updated appointment
|
|
13011
|
+
* User rejects a reschedule proposed by the clinic.
|
|
13012
|
+
* Status changes from RESCHEDULED_BY_CLINIC to CANCELED_PATIENT_RESCHEDULED.
|
|
12710
13013
|
*/
|
|
12711
|
-
async
|
|
13014
|
+
async rescheduleAppointmentRejectUser(appointmentId, reason) {
|
|
12712
13015
|
console.log(
|
|
12713
|
-
`[APPOINTMENT_SERVICE]
|
|
13016
|
+
`[APPOINTMENT_SERVICE] User rejecting reschedule for: ${appointmentId}`
|
|
12714
13017
|
);
|
|
13018
|
+
const appointment = await this.getAppointmentById(appointmentId);
|
|
13019
|
+
if (!appointment)
|
|
13020
|
+
throw new Error(`Appointment ${appointmentId} not found.`);
|
|
13021
|
+
if (appointment.status !== "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */) {
|
|
13022
|
+
throw new Error(
|
|
13023
|
+
`Appointment ${appointmentId} is not in RESCHEDULED_BY_CLINIC state.`
|
|
13024
|
+
);
|
|
13025
|
+
}
|
|
12715
13026
|
return this.updateAppointmentStatus(
|
|
12716
13027
|
appointmentId,
|
|
12717
|
-
"
|
|
13028
|
+
"canceled_patient_rescheduled" /* CANCELED_PATIENT_RESCHEDULED */,
|
|
13029
|
+
{
|
|
13030
|
+
cancellationReason: reason,
|
|
13031
|
+
canceledBy: "patient"
|
|
13032
|
+
}
|
|
12718
13033
|
);
|
|
12719
13034
|
}
|
|
12720
13035
|
/**
|
|
12721
|
-
*
|
|
12722
|
-
*
|
|
12723
|
-
* @param appointmentId ID of the appointment
|
|
12724
|
-
* @returns The updated appointment
|
|
13036
|
+
* Admin checks in a patient for their appointment.
|
|
13037
|
+
* Requires all pending user forms to be completed.
|
|
12725
13038
|
*/
|
|
12726
|
-
async
|
|
12727
|
-
console.log(
|
|
13039
|
+
async checkInPatientAdmin(appointmentId) {
|
|
13040
|
+
console.log(
|
|
13041
|
+
`[APPOINTMENT_SERVICE] Admin checking in patient for: ${appointmentId}`
|
|
13042
|
+
);
|
|
13043
|
+
const appointment = await this.getAppointmentById(appointmentId);
|
|
13044
|
+
if (!appointment)
|
|
13045
|
+
throw new Error(`Appointment ${appointmentId} not found.`);
|
|
13046
|
+
if (appointment.pendingUserFormsIds && appointment.pendingUserFormsIds.length > 0) {
|
|
13047
|
+
throw new Error(
|
|
13048
|
+
`Cannot check in: Patient has ${appointment.pendingUserFormsIds.length} pending required form(s). IDs: ${appointment.pendingUserFormsIds.join(
|
|
13049
|
+
", "
|
|
13050
|
+
)}`
|
|
13051
|
+
);
|
|
13052
|
+
}
|
|
13053
|
+
if (appointment.status !== "confirmed" /* CONFIRMED */ && appointment.status !== "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */) {
|
|
13054
|
+
console.warn(
|
|
13055
|
+
`Checking in appointment ${appointmentId} with status ${appointment.status}. Ensure this is intended.`
|
|
13056
|
+
);
|
|
13057
|
+
}
|
|
12728
13058
|
return this.updateAppointmentStatus(
|
|
12729
13059
|
appointmentId,
|
|
12730
|
-
"
|
|
13060
|
+
"checked_in" /* CHECKED_IN */
|
|
12731
13061
|
);
|
|
12732
13062
|
}
|
|
12733
13063
|
/**
|
|
12734
|
-
*
|
|
12735
|
-
*
|
|
12736
|
-
* @param appointmentId ID of the appointment
|
|
12737
|
-
* @param actualDurationMinutes Actual duration of the appointment in minutes
|
|
12738
|
-
* @returns The updated appointment
|
|
13064
|
+
* Doctor starts the appointment procedure.
|
|
12739
13065
|
*/
|
|
12740
|
-
async
|
|
13066
|
+
async startAppointmentDoctor(appointmentId) {
|
|
12741
13067
|
console.log(
|
|
12742
|
-
`[APPOINTMENT_SERVICE]
|
|
13068
|
+
`[APPOINTMENT_SERVICE] Doctor starting appointment: ${appointmentId}`
|
|
12743
13069
|
);
|
|
13070
|
+
const appointment = await this.getAppointmentById(appointmentId);
|
|
13071
|
+
if (!appointment)
|
|
13072
|
+
throw new Error(`Appointment ${appointmentId} not found.`);
|
|
13073
|
+
if (appointment.status !== "checked_in" /* CHECKED_IN */) {
|
|
13074
|
+
throw new Error(
|
|
13075
|
+
`Appointment ${appointmentId} must be CHECKED_IN to start.`
|
|
13076
|
+
);
|
|
13077
|
+
}
|
|
13078
|
+
const updateData = {
|
|
13079
|
+
status: "in_progress" /* IN_PROGRESS */,
|
|
13080
|
+
procedureActualStartTime: import_firestore40.Timestamp.now(),
|
|
13081
|
+
// Set actual start time
|
|
13082
|
+
updatedAt: (0, import_firestore40.serverTimestamp)()
|
|
13083
|
+
};
|
|
13084
|
+
return this.updateAppointment(appointmentId, updateData);
|
|
13085
|
+
}
|
|
13086
|
+
/**
|
|
13087
|
+
* Doctor completes and finalizes the appointment.
|
|
13088
|
+
*/
|
|
13089
|
+
async completeAppointmentDoctor(appointmentId, finalizationNotes, actualDurationMinutesInput) {
|
|
13090
|
+
console.log(
|
|
13091
|
+
`[APPOINTMENT_SERVICE] Doctor completing appointment: ${appointmentId}`
|
|
13092
|
+
);
|
|
13093
|
+
const currentUser = this.auth.currentUser;
|
|
13094
|
+
if (!currentUser)
|
|
13095
|
+
throw new Error("Authentication required to complete appointment.");
|
|
13096
|
+
const appointment = await this.getAppointmentById(appointmentId);
|
|
13097
|
+
if (!appointment)
|
|
13098
|
+
throw new Error(`Appointment ${appointmentId} not found.`);
|
|
13099
|
+
let calculatedDurationMinutes = actualDurationMinutesInput;
|
|
13100
|
+
const procedureCompletionTime = import_firestore40.Timestamp.now();
|
|
13101
|
+
if (calculatedDurationMinutes === void 0 && appointment.procedureActualStartTime) {
|
|
13102
|
+
const startTimeMillis = appointment.procedureActualStartTime.toMillis();
|
|
13103
|
+
const endTimeMillis = procedureCompletionTime.toMillis();
|
|
13104
|
+
if (endTimeMillis > startTimeMillis) {
|
|
13105
|
+
calculatedDurationMinutes = Math.round(
|
|
13106
|
+
(endTimeMillis - startTimeMillis) / 6e4
|
|
13107
|
+
);
|
|
13108
|
+
}
|
|
13109
|
+
}
|
|
12744
13110
|
const updateData = {
|
|
12745
13111
|
status: "completed" /* COMPLETED */,
|
|
12746
|
-
actualDurationMinutes
|
|
13112
|
+
actualDurationMinutes: calculatedDurationMinutes,
|
|
13113
|
+
// Use calculated or provided duration
|
|
13114
|
+
finalizedDetails: {
|
|
13115
|
+
by: currentUser.uid,
|
|
13116
|
+
// This is used ID, not practitioner's profile ID (just so we know who completed the appointment)
|
|
13117
|
+
at: procedureCompletionTime,
|
|
13118
|
+
// Use consistent completion timestamp
|
|
13119
|
+
notes: finalizationNotes
|
|
13120
|
+
},
|
|
13121
|
+
// Optionally update appointmentEndTime to the actual completion time
|
|
13122
|
+
// appointmentEndTime: procedureCompletionTime,
|
|
13123
|
+
updatedAt: (0, import_firestore40.serverTimestamp)()
|
|
12747
13124
|
};
|
|
12748
13125
|
return this.updateAppointment(appointmentId, updateData);
|
|
12749
13126
|
}
|
|
12750
13127
|
/**
|
|
12751
|
-
*
|
|
12752
|
-
*
|
|
12753
|
-
* @param appointmentId ID of the appointment
|
|
12754
|
-
* @returns The updated appointment
|
|
13128
|
+
* Admin marks an appointment as No-Show.
|
|
12755
13129
|
*/
|
|
12756
|
-
async
|
|
13130
|
+
async markNoShowAdmin(appointmentId) {
|
|
12757
13131
|
console.log(
|
|
12758
|
-
`[APPOINTMENT_SERVICE]
|
|
13132
|
+
`[APPOINTMENT_SERVICE] Admin marking no-show for: ${appointmentId}`
|
|
12759
13133
|
);
|
|
13134
|
+
const appointment = await this.getAppointmentById(appointmentId);
|
|
13135
|
+
if (!appointment)
|
|
13136
|
+
throw new Error(`Appointment ${appointmentId} not found.`);
|
|
13137
|
+
if (import_firestore40.Timestamp.now().toMillis() < appointment.appointmentStartTime.toMillis()) {
|
|
13138
|
+
throw new Error("Cannot mark no-show before appointment start time.");
|
|
13139
|
+
}
|
|
12760
13140
|
return this.updateAppointmentStatus(
|
|
12761
13141
|
appointmentId,
|
|
12762
|
-
"no_show" /* NO_SHOW
|
|
13142
|
+
"no_show" /* NO_SHOW */,
|
|
13143
|
+
{
|
|
13144
|
+
cancellationReason: "Patient did not show up for the appointment.",
|
|
13145
|
+
canceledBy: "clinic"
|
|
13146
|
+
}
|
|
12763
13147
|
);
|
|
12764
13148
|
}
|
|
13149
|
+
/**
|
|
13150
|
+
* Adds a media item to an appointment.
|
|
13151
|
+
*/
|
|
13152
|
+
async addMediaToAppointment(appointmentId, mediaItemData) {
|
|
13153
|
+
console.log(
|
|
13154
|
+
`[APPOINTMENT_SERVICE] Adding media to appointment ${appointmentId}`
|
|
13155
|
+
);
|
|
13156
|
+
const currentUser = this.auth.currentUser;
|
|
13157
|
+
if (!currentUser) throw new Error("Authentication required.");
|
|
13158
|
+
const newMediaItem = {
|
|
13159
|
+
...mediaItemData,
|
|
13160
|
+
id: this.generateId(),
|
|
13161
|
+
uploadedAt: import_firestore40.Timestamp.now(),
|
|
13162
|
+
uploadedBy: currentUser.uid
|
|
13163
|
+
};
|
|
13164
|
+
const updateData = {
|
|
13165
|
+
media: (0, import_firestore40.arrayUnion)(newMediaItem),
|
|
13166
|
+
updatedAt: (0, import_firestore40.serverTimestamp)()
|
|
13167
|
+
};
|
|
13168
|
+
return this.updateAppointment(appointmentId, updateData);
|
|
13169
|
+
}
|
|
13170
|
+
/**
|
|
13171
|
+
* Removes a media item from an appointment.
|
|
13172
|
+
*/
|
|
13173
|
+
async removeMediaFromAppointment(appointmentId, mediaItemId) {
|
|
13174
|
+
console.log(
|
|
13175
|
+
`[APPOINTMENT_SERVICE] Removing media ${mediaItemId} from appointment ${appointmentId}`
|
|
13176
|
+
);
|
|
13177
|
+
const appointment = await this.getAppointmentById(appointmentId);
|
|
13178
|
+
if (!appointment || !appointment.media) {
|
|
13179
|
+
throw new Error("Appointment or media list not found.");
|
|
13180
|
+
}
|
|
13181
|
+
const mediaToRemove = appointment.media.find((m) => m.id === mediaItemId);
|
|
13182
|
+
if (!mediaToRemove) {
|
|
13183
|
+
throw new Error(`Media item ${mediaItemId} not found in appointment.`);
|
|
13184
|
+
}
|
|
13185
|
+
const updateData = {
|
|
13186
|
+
media: (0, import_firestore40.arrayRemove)(mediaToRemove),
|
|
13187
|
+
updatedAt: (0, import_firestore40.serverTimestamp)()
|
|
13188
|
+
};
|
|
13189
|
+
return this.updateAppointment(appointmentId, updateData);
|
|
13190
|
+
}
|
|
13191
|
+
/**
|
|
13192
|
+
* Adds or updates review information for an appointment.
|
|
13193
|
+
*/
|
|
13194
|
+
async addReviewToAppointment(appointmentId, reviewData) {
|
|
13195
|
+
console.log(
|
|
13196
|
+
`[APPOINTMENT_SERVICE] Adding review to appointment ${appointmentId}`
|
|
13197
|
+
);
|
|
13198
|
+
const newReviewInfo = {
|
|
13199
|
+
...reviewData,
|
|
13200
|
+
reviewId: this.generateId(),
|
|
13201
|
+
reviewedAt: import_firestore40.Timestamp.now()
|
|
13202
|
+
};
|
|
13203
|
+
const updateData = {
|
|
13204
|
+
reviewInfo: newReviewInfo,
|
|
13205
|
+
updatedAt: (0, import_firestore40.serverTimestamp)()
|
|
13206
|
+
};
|
|
13207
|
+
return this.updateAppointment(appointmentId, updateData);
|
|
13208
|
+
}
|
|
12765
13209
|
/**
|
|
12766
13210
|
* Updates the payment status of an appointment.
|
|
12767
|
-
*
|
|
12768
|
-
* @param appointmentId ID of the appointment
|
|
12769
|
-
* @param paymentStatus New payment status
|
|
12770
|
-
* @param paymentTransactionId Optional transaction ID for the payment
|
|
12771
|
-
* @returns The updated appointment
|
|
12772
13211
|
*/
|
|
12773
13212
|
async updatePaymentStatus(appointmentId, paymentStatus, paymentTransactionId) {
|
|
12774
13213
|
console.log(
|
|
@@ -12776,7 +13215,8 @@ var AppointmentService = class extends BaseService {
|
|
|
12776
13215
|
);
|
|
12777
13216
|
const updateData = {
|
|
12778
13217
|
paymentStatus,
|
|
12779
|
-
paymentTransactionId: paymentTransactionId || null
|
|
13218
|
+
paymentTransactionId: paymentTransactionId || null,
|
|
13219
|
+
updatedAt: (0, import_firestore40.serverTimestamp)()
|
|
12780
13220
|
};
|
|
12781
13221
|
return this.updateAppointment(appointmentId, updateData);
|
|
12782
13222
|
}
|
|
@@ -12849,9 +13289,203 @@ var AppointmentService = class extends BaseService {
|
|
|
12849
13289
|
}
|
|
12850
13290
|
};
|
|
12851
13291
|
|
|
12852
|
-
// src/
|
|
13292
|
+
// src/services/patient/patientRequirements.service.ts
|
|
12853
13293
|
var import_firestore41 = require("firebase/firestore");
|
|
12854
13294
|
|
|
13295
|
+
// src/types/patient/patient-requirements.ts
|
|
13296
|
+
var PatientInstructionStatus = /* @__PURE__ */ ((PatientInstructionStatus2) => {
|
|
13297
|
+
PatientInstructionStatus2["PENDING_NOTIFICATION"] = "pendingNotification";
|
|
13298
|
+
PatientInstructionStatus2["ACTION_DUE"] = "actionDue";
|
|
13299
|
+
PatientInstructionStatus2["ACTION_TAKEN"] = "actionTaken";
|
|
13300
|
+
PatientInstructionStatus2["MISSED"] = "missed";
|
|
13301
|
+
PatientInstructionStatus2["CANCELLED"] = "cancelled";
|
|
13302
|
+
PatientInstructionStatus2["SKIPPED"] = "skipped";
|
|
13303
|
+
return PatientInstructionStatus2;
|
|
13304
|
+
})(PatientInstructionStatus || {});
|
|
13305
|
+
var PatientRequirementOverallStatus = /* @__PURE__ */ ((PatientRequirementOverallStatus2) => {
|
|
13306
|
+
PatientRequirementOverallStatus2["ACTIVE"] = "active";
|
|
13307
|
+
PatientRequirementOverallStatus2["ALL_INSTRUCTIONS_MET"] = "allInstructionsMet";
|
|
13308
|
+
PatientRequirementOverallStatus2["PARTIALLY_COMPLETED"] = "partiallyCompleted";
|
|
13309
|
+
PatientRequirementOverallStatus2["FAILED"] = "failed";
|
|
13310
|
+
PatientRequirementOverallStatus2["CANCELLED_APPOINTMENT"] = "cancelledAppointment";
|
|
13311
|
+
PatientRequirementOverallStatus2["SUPERSEDED_RESCHEDULE"] = "supersededReschedule";
|
|
13312
|
+
PatientRequirementOverallStatus2["FAILED_TO_PROCESS"] = "failedToProcess";
|
|
13313
|
+
return PatientRequirementOverallStatus2;
|
|
13314
|
+
})(PatientRequirementOverallStatus || {});
|
|
13315
|
+
var PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME = "patientRequirements";
|
|
13316
|
+
|
|
13317
|
+
// src/services/patient/patientRequirements.service.ts
|
|
13318
|
+
var PatientRequirementsService = class extends BaseService {
|
|
13319
|
+
constructor(db, auth, app) {
|
|
13320
|
+
super(db, auth, app);
|
|
13321
|
+
}
|
|
13322
|
+
getPatientRequirementsCollectionRef(patientId) {
|
|
13323
|
+
return (0, import_firestore41.collection)(
|
|
13324
|
+
this.db,
|
|
13325
|
+
`patients/${patientId}/${PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME}`
|
|
13326
|
+
);
|
|
13327
|
+
}
|
|
13328
|
+
getPatientRequirementDocRef(patientId, instanceId) {
|
|
13329
|
+
return (0, import_firestore41.doc)(
|
|
13330
|
+
this.getPatientRequirementsCollectionRef(patientId),
|
|
13331
|
+
instanceId
|
|
13332
|
+
);
|
|
13333
|
+
}
|
|
13334
|
+
/**
|
|
13335
|
+
* Gets a specific patient requirement instance by its ID.
|
|
13336
|
+
* @param patientId - The ID of the patient.
|
|
13337
|
+
* @param instanceId - The ID of the requirement instance.
|
|
13338
|
+
* @returns The patient requirement instance or null if not found.
|
|
13339
|
+
*/
|
|
13340
|
+
async getPatientRequirementInstance(patientId, instanceId) {
|
|
13341
|
+
const docRef = this.getPatientRequirementDocRef(patientId, instanceId);
|
|
13342
|
+
const docSnap = await (0, import_firestore41.getDoc)(docRef);
|
|
13343
|
+
if (!docSnap.exists()) {
|
|
13344
|
+
return null;
|
|
13345
|
+
}
|
|
13346
|
+
const data = docSnap.data();
|
|
13347
|
+
return { id: docSnap.id, ...data };
|
|
13348
|
+
}
|
|
13349
|
+
/**
|
|
13350
|
+
* Retrieves patient requirement instances based on specified filters.
|
|
13351
|
+
* This is a flexible query method.
|
|
13352
|
+
*
|
|
13353
|
+
* @param patientId - The ID of the patient.
|
|
13354
|
+
* @param filters - Optional filters for appointmentId, overall statuses, instruction statuses, and due timeframes.
|
|
13355
|
+
* @param pageLimit - Optional limit for pagination.
|
|
13356
|
+
* @param lastVisible - Optional last document snapshot for pagination.
|
|
13357
|
+
* @returns A promise resolving to an array of matching patient requirement instances and the last document snapshot.
|
|
13358
|
+
*/
|
|
13359
|
+
async getAllPatientRequirementInstances(patientId, filters, pageLimit = 20, lastVisible) {
|
|
13360
|
+
const collRef = this.getPatientRequirementsCollectionRef(patientId);
|
|
13361
|
+
let q = (0, import_firestore41.query)(collRef, (0, import_firestore41.orderBy)("createdAt", "desc"));
|
|
13362
|
+
const queryConstraints = [];
|
|
13363
|
+
if ((filters == null ? void 0 : filters.appointmentId) && filters.appointmentId !== "all") {
|
|
13364
|
+
queryConstraints.push(
|
|
13365
|
+
(0, import_firestore41.where)("appointmentId", "==", filters.appointmentId)
|
|
13366
|
+
);
|
|
13367
|
+
}
|
|
13368
|
+
if ((filters == null ? void 0 : filters.statuses) && filters.statuses.length > 0) {
|
|
13369
|
+
queryConstraints.push((0, import_firestore41.where)("overallStatus", "in", filters.statuses));
|
|
13370
|
+
}
|
|
13371
|
+
if (lastVisible) {
|
|
13372
|
+
queryConstraints.push((0, import_firestore41.startAfter)(lastVisible));
|
|
13373
|
+
}
|
|
13374
|
+
queryConstraints.push((0, import_firestore41.limit)(pageLimit));
|
|
13375
|
+
q = (0, import_firestore41.query)(collRef, ...queryConstraints);
|
|
13376
|
+
const snapshot = await (0, import_firestore41.getDocs)(q);
|
|
13377
|
+
let requirements = snapshot.docs.map((docSnap) => {
|
|
13378
|
+
const data = docSnap.data();
|
|
13379
|
+
return { id: docSnap.id, ...data };
|
|
13380
|
+
});
|
|
13381
|
+
if ((filters == null ? void 0 : filters.instructionStatuses) && filters.instructionStatuses.length > 0) {
|
|
13382
|
+
requirements = requirements.filter(
|
|
13383
|
+
(req) => req.instructions.some(
|
|
13384
|
+
(instr) => filters.instructionStatuses.includes(instr.status)
|
|
13385
|
+
)
|
|
13386
|
+
);
|
|
13387
|
+
}
|
|
13388
|
+
if (filters == null ? void 0 : filters.dueBefore) {
|
|
13389
|
+
const dueBeforeMillis = filters.dueBefore.toMillis();
|
|
13390
|
+
requirements = requirements.filter(
|
|
13391
|
+
(req) => req.instructions.some(
|
|
13392
|
+
(instr) => instr.dueTime.toMillis() < dueBeforeMillis
|
|
13393
|
+
)
|
|
13394
|
+
);
|
|
13395
|
+
}
|
|
13396
|
+
if (filters == null ? void 0 : filters.dueAfter) {
|
|
13397
|
+
const dueAfterMillis = filters.dueAfter.toMillis();
|
|
13398
|
+
requirements = requirements.filter(
|
|
13399
|
+
(req) => req.instructions.some(
|
|
13400
|
+
(instr) => instr.dueTime.toMillis() > dueAfterMillis
|
|
13401
|
+
)
|
|
13402
|
+
);
|
|
13403
|
+
}
|
|
13404
|
+
const newLastVisible = snapshot.docs[snapshot.docs.length - 1] || null;
|
|
13405
|
+
return { requirements, lastDoc: newLastVisible };
|
|
13406
|
+
}
|
|
13407
|
+
/**
|
|
13408
|
+
* Marks a specific instruction within a PatientRequirementInstance as ACTION_TAKEN.
|
|
13409
|
+
* If all instructions are actioned, updates the overallStatus of the instance.
|
|
13410
|
+
*
|
|
13411
|
+
* @param patientId - The ID of the patient.
|
|
13412
|
+
* @param instanceId - The ID of the PatientRequirementInstance.
|
|
13413
|
+
* @param instructionId - The ID of the instruction to complete.
|
|
13414
|
+
* @returns The updated PatientRequirementInstance.
|
|
13415
|
+
* @throws Error if the instance or instruction is not found, or if the instruction is not in a completable state.
|
|
13416
|
+
*/
|
|
13417
|
+
async completeInstruction(patientId, instanceId, instructionId) {
|
|
13418
|
+
const instanceRef = this.getPatientRequirementDocRef(patientId, instanceId);
|
|
13419
|
+
const instanceSnap = await (0, import_firestore41.getDoc)(instanceRef);
|
|
13420
|
+
if (!instanceSnap.exists()) {
|
|
13421
|
+
throw new Error(
|
|
13422
|
+
`PatientRequirementInstance ${instanceId} not found for patient ${patientId}.`
|
|
13423
|
+
);
|
|
13424
|
+
}
|
|
13425
|
+
const instanceData = instanceSnap.data();
|
|
13426
|
+
const instance = { id: instanceSnap.id, ...instanceData };
|
|
13427
|
+
const instructionIndex = instance.instructions.findIndex(
|
|
13428
|
+
(instr) => instr.instructionId === instructionId
|
|
13429
|
+
);
|
|
13430
|
+
if (instructionIndex === -1) {
|
|
13431
|
+
throw new Error(
|
|
13432
|
+
`Instruction ${instructionId} not found in instance ${instanceId}.`
|
|
13433
|
+
);
|
|
13434
|
+
}
|
|
13435
|
+
const instructionToUpdate = instance.instructions[instructionIndex];
|
|
13436
|
+
if (instructionToUpdate.status !== "pendingNotification" /* PENDING_NOTIFICATION */ && instructionToUpdate.status !== "actionDue" /* ACTION_DUE */ && instructionToUpdate.status !== "missed" /* MISSED */) {
|
|
13437
|
+
if (instructionToUpdate.status === "actionTaken" /* ACTION_TAKEN */) {
|
|
13438
|
+
console.warn(
|
|
13439
|
+
`Instruction ${instructionId} is already marked as ACTION_TAKEN.`
|
|
13440
|
+
);
|
|
13441
|
+
return instance;
|
|
13442
|
+
}
|
|
13443
|
+
throw new Error(
|
|
13444
|
+
`Instruction ${instructionId} is in status ${instructionToUpdate.status} and cannot be marked as completed.`
|
|
13445
|
+
);
|
|
13446
|
+
}
|
|
13447
|
+
const now = import_firestore41.Timestamp.now();
|
|
13448
|
+
const updatedInstructions = [...instance.instructions];
|
|
13449
|
+
updatedInstructions[instructionIndex] = {
|
|
13450
|
+
...instructionToUpdate,
|
|
13451
|
+
status: "actionTaken" /* ACTION_TAKEN */,
|
|
13452
|
+
actionTakenAt: now,
|
|
13453
|
+
updatedAt: now
|
|
13454
|
+
};
|
|
13455
|
+
const allActionTaken = updatedInstructions.every(
|
|
13456
|
+
(instr) => instr.status === "actionTaken" /* ACTION_TAKEN */
|
|
13457
|
+
);
|
|
13458
|
+
let newOverallStatus = instance.overallStatus;
|
|
13459
|
+
if (allActionTaken) {
|
|
13460
|
+
newOverallStatus = "allInstructionsMet" /* ALL_INSTRUCTIONS_MET */;
|
|
13461
|
+
} else if (updatedInstructions.some(
|
|
13462
|
+
(instr) => instr.status === "actionTaken" /* ACTION_TAKEN */
|
|
13463
|
+
)) {
|
|
13464
|
+
newOverallStatus = "partiallyCompleted" /* PARTIALLY_COMPLETED */;
|
|
13465
|
+
}
|
|
13466
|
+
const updatePayload = {
|
|
13467
|
+
// Using a general type for updateDoc payload
|
|
13468
|
+
instructions: updatedInstructions,
|
|
13469
|
+
updatedAt: now
|
|
13470
|
+
};
|
|
13471
|
+
if (newOverallStatus !== instance.overallStatus) {
|
|
13472
|
+
updatePayload.overallStatus = newOverallStatus;
|
|
13473
|
+
}
|
|
13474
|
+
await (0, import_firestore41.updateDoc)(instanceRef, updatePayload);
|
|
13475
|
+
return {
|
|
13476
|
+
...instance,
|
|
13477
|
+
instructions: updatedInstructions,
|
|
13478
|
+
updatedAt: now,
|
|
13479
|
+
overallStatus: newOverallStatus
|
|
13480
|
+
};
|
|
13481
|
+
}
|
|
13482
|
+
// Note: As per the request, full CRUD (create, direct update of instance, delete) is not part of this light service,
|
|
13483
|
+
// as those will be handled by Cloud Functions reacting to appointment lifecycle events.
|
|
13484
|
+
};
|
|
13485
|
+
|
|
13486
|
+
// src/backoffice/services/brand.service.ts
|
|
13487
|
+
var import_firestore42 = require("firebase/firestore");
|
|
13488
|
+
|
|
12855
13489
|
// src/backoffice/types/brand.types.ts
|
|
12856
13490
|
var BRANDS_COLLECTION = "brands";
|
|
12857
13491
|
|
|
@@ -12861,7 +13495,7 @@ var BrandService = class extends BaseService {
|
|
|
12861
13495
|
* Gets reference to brands collection
|
|
12862
13496
|
*/
|
|
12863
13497
|
getBrandsRef() {
|
|
12864
|
-
return (0,
|
|
13498
|
+
return (0, import_firestore42.collection)(this.db, BRANDS_COLLECTION);
|
|
12865
13499
|
}
|
|
12866
13500
|
/**
|
|
12867
13501
|
* Creates a new brand
|
|
@@ -12874,19 +13508,19 @@ var BrandService = class extends BaseService {
|
|
|
12874
13508
|
updatedAt: now,
|
|
12875
13509
|
isActive: true
|
|
12876
13510
|
};
|
|
12877
|
-
const docRef = await (0,
|
|
13511
|
+
const docRef = await (0, import_firestore42.addDoc)(this.getBrandsRef(), newBrand);
|
|
12878
13512
|
return { id: docRef.id, ...newBrand };
|
|
12879
13513
|
}
|
|
12880
13514
|
/**
|
|
12881
13515
|
* Gets all active brands
|
|
12882
13516
|
*/
|
|
12883
13517
|
async getAll() {
|
|
12884
|
-
const q = (0,
|
|
12885
|
-
const snapshot = await (0,
|
|
13518
|
+
const q = (0, import_firestore42.query)(this.getBrandsRef(), (0, import_firestore42.where)("isActive", "==", true));
|
|
13519
|
+
const snapshot = await (0, import_firestore42.getDocs)(q);
|
|
12886
13520
|
return snapshot.docs.map(
|
|
12887
|
-
(
|
|
12888
|
-
id:
|
|
12889
|
-
...
|
|
13521
|
+
(doc33) => ({
|
|
13522
|
+
id: doc33.id,
|
|
13523
|
+
...doc33.data()
|
|
12890
13524
|
})
|
|
12891
13525
|
);
|
|
12892
13526
|
}
|
|
@@ -12898,8 +13532,8 @@ var BrandService = class extends BaseService {
|
|
|
12898
13532
|
...brand,
|
|
12899
13533
|
updatedAt: /* @__PURE__ */ new Date()
|
|
12900
13534
|
};
|
|
12901
|
-
const docRef = (0,
|
|
12902
|
-
await (0,
|
|
13535
|
+
const docRef = (0, import_firestore42.doc)(this.getBrandsRef(), brandId);
|
|
13536
|
+
await (0, import_firestore42.updateDoc)(docRef, updateData);
|
|
12903
13537
|
return this.getById(brandId);
|
|
12904
13538
|
}
|
|
12905
13539
|
/**
|
|
@@ -12914,8 +13548,8 @@ var BrandService = class extends BaseService {
|
|
|
12914
13548
|
* Gets a brand by ID
|
|
12915
13549
|
*/
|
|
12916
13550
|
async getById(brandId) {
|
|
12917
|
-
const docRef = (0,
|
|
12918
|
-
const docSnap = await (0,
|
|
13551
|
+
const docRef = (0, import_firestore42.doc)(this.getBrandsRef(), brandId);
|
|
13552
|
+
const docSnap = await (0, import_firestore42.getDoc)(docRef);
|
|
12919
13553
|
if (!docSnap.exists()) return null;
|
|
12920
13554
|
return {
|
|
12921
13555
|
id: docSnap.id,
|
|
@@ -12925,7 +13559,7 @@ var BrandService = class extends BaseService {
|
|
|
12925
13559
|
};
|
|
12926
13560
|
|
|
12927
13561
|
// src/backoffice/services/category.service.ts
|
|
12928
|
-
var
|
|
13562
|
+
var import_firestore43 = require("firebase/firestore");
|
|
12929
13563
|
|
|
12930
13564
|
// src/backoffice/types/category.types.ts
|
|
12931
13565
|
var CATEGORIES_COLLECTION = "backoffice_categories";
|
|
@@ -12936,7 +13570,7 @@ var CategoryService = class extends BaseService {
|
|
|
12936
13570
|
* Referenca na Firestore kolekciju kategorija
|
|
12937
13571
|
*/
|
|
12938
13572
|
get categoriesRef() {
|
|
12939
|
-
return (0,
|
|
13573
|
+
return (0, import_firestore43.collection)(this.db, CATEGORIES_COLLECTION);
|
|
12940
13574
|
}
|
|
12941
13575
|
/**
|
|
12942
13576
|
* Kreira novu kategoriju u sistemu
|
|
@@ -12951,7 +13585,7 @@ var CategoryService = class extends BaseService {
|
|
|
12951
13585
|
updatedAt: now,
|
|
12952
13586
|
isActive: true
|
|
12953
13587
|
};
|
|
12954
|
-
const docRef = await (0,
|
|
13588
|
+
const docRef = await (0, import_firestore43.addDoc)(this.categoriesRef, newCategory);
|
|
12955
13589
|
return { id: docRef.id, ...newCategory };
|
|
12956
13590
|
}
|
|
12957
13591
|
/**
|
|
@@ -12959,12 +13593,12 @@ var CategoryService = class extends BaseService {
|
|
|
12959
13593
|
* @returns Lista aktivnih kategorija
|
|
12960
13594
|
*/
|
|
12961
13595
|
async getAll() {
|
|
12962
|
-
const q = (0,
|
|
12963
|
-
const snapshot = await (0,
|
|
13596
|
+
const q = (0, import_firestore43.query)(this.categoriesRef, (0, import_firestore43.where)("isActive", "==", true));
|
|
13597
|
+
const snapshot = await (0, import_firestore43.getDocs)(q);
|
|
12964
13598
|
return snapshot.docs.map(
|
|
12965
|
-
(
|
|
12966
|
-
id:
|
|
12967
|
-
...
|
|
13599
|
+
(doc33) => ({
|
|
13600
|
+
id: doc33.id,
|
|
13601
|
+
...doc33.data()
|
|
12968
13602
|
})
|
|
12969
13603
|
);
|
|
12970
13604
|
}
|
|
@@ -12974,16 +13608,16 @@ var CategoryService = class extends BaseService {
|
|
|
12974
13608
|
* @returns Lista kategorija koje pripadaju traženoj familiji
|
|
12975
13609
|
*/
|
|
12976
13610
|
async getAllByFamily(family) {
|
|
12977
|
-
const q = (0,
|
|
13611
|
+
const q = (0, import_firestore43.query)(
|
|
12978
13612
|
this.categoriesRef,
|
|
12979
|
-
(0,
|
|
12980
|
-
(0,
|
|
13613
|
+
(0, import_firestore43.where)("family", "==", family),
|
|
13614
|
+
(0, import_firestore43.where)("isActive", "==", true)
|
|
12981
13615
|
);
|
|
12982
|
-
const snapshot = await (0,
|
|
13616
|
+
const snapshot = await (0, import_firestore43.getDocs)(q);
|
|
12983
13617
|
return snapshot.docs.map(
|
|
12984
|
-
(
|
|
12985
|
-
id:
|
|
12986
|
-
...
|
|
13618
|
+
(doc33) => ({
|
|
13619
|
+
id: doc33.id,
|
|
13620
|
+
...doc33.data()
|
|
12987
13621
|
})
|
|
12988
13622
|
);
|
|
12989
13623
|
}
|
|
@@ -12998,8 +13632,8 @@ var CategoryService = class extends BaseService {
|
|
|
12998
13632
|
...category,
|
|
12999
13633
|
updatedAt: /* @__PURE__ */ new Date()
|
|
13000
13634
|
};
|
|
13001
|
-
const docRef = (0,
|
|
13002
|
-
await (0,
|
|
13635
|
+
const docRef = (0, import_firestore43.doc)(this.categoriesRef, id);
|
|
13636
|
+
await (0, import_firestore43.updateDoc)(docRef, updateData);
|
|
13003
13637
|
return this.getById(id);
|
|
13004
13638
|
}
|
|
13005
13639
|
/**
|
|
@@ -13015,8 +13649,8 @@ var CategoryService = class extends BaseService {
|
|
|
13015
13649
|
* @returns Kategorija ili null ako ne postoji
|
|
13016
13650
|
*/
|
|
13017
13651
|
async getById(id) {
|
|
13018
|
-
const docRef = (0,
|
|
13019
|
-
const docSnap = await (0,
|
|
13652
|
+
const docRef = (0, import_firestore43.doc)(this.categoriesRef, id);
|
|
13653
|
+
const docSnap = await (0, import_firestore43.getDoc)(docRef);
|
|
13020
13654
|
if (!docSnap.exists()) return null;
|
|
13021
13655
|
return {
|
|
13022
13656
|
id: docSnap.id,
|
|
@@ -13026,7 +13660,7 @@ var CategoryService = class extends BaseService {
|
|
|
13026
13660
|
};
|
|
13027
13661
|
|
|
13028
13662
|
// src/backoffice/services/subcategory.service.ts
|
|
13029
|
-
var
|
|
13663
|
+
var import_firestore44 = require("firebase/firestore");
|
|
13030
13664
|
|
|
13031
13665
|
// src/backoffice/types/subcategory.types.ts
|
|
13032
13666
|
var SUBCATEGORIES_COLLECTION = "subcategories";
|
|
@@ -13038,7 +13672,7 @@ var SubcategoryService = class extends BaseService {
|
|
|
13038
13672
|
* @param categoryId - ID roditeljske kategorije
|
|
13039
13673
|
*/
|
|
13040
13674
|
getSubcategoriesRef(categoryId) {
|
|
13041
|
-
return (0,
|
|
13675
|
+
return (0, import_firestore44.collection)(
|
|
13042
13676
|
this.db,
|
|
13043
13677
|
CATEGORIES_COLLECTION,
|
|
13044
13678
|
categoryId,
|
|
@@ -13060,7 +13694,7 @@ var SubcategoryService = class extends BaseService {
|
|
|
13060
13694
|
updatedAt: now,
|
|
13061
13695
|
isActive: true
|
|
13062
13696
|
};
|
|
13063
|
-
const docRef = await (0,
|
|
13697
|
+
const docRef = await (0, import_firestore44.addDoc)(
|
|
13064
13698
|
this.getSubcategoriesRef(categoryId),
|
|
13065
13699
|
newSubcategory
|
|
13066
13700
|
);
|
|
@@ -13072,15 +13706,15 @@ var SubcategoryService = class extends BaseService {
|
|
|
13072
13706
|
* @returns Lista aktivnih podkategorija
|
|
13073
13707
|
*/
|
|
13074
13708
|
async getAllByCategoryId(categoryId) {
|
|
13075
|
-
const q = (0,
|
|
13709
|
+
const q = (0, import_firestore44.query)(
|
|
13076
13710
|
this.getSubcategoriesRef(categoryId),
|
|
13077
|
-
(0,
|
|
13711
|
+
(0, import_firestore44.where)("isActive", "==", true)
|
|
13078
13712
|
);
|
|
13079
|
-
const snapshot = await (0,
|
|
13713
|
+
const snapshot = await (0, import_firestore44.getDocs)(q);
|
|
13080
13714
|
return snapshot.docs.map(
|
|
13081
|
-
(
|
|
13082
|
-
id:
|
|
13083
|
-
...
|
|
13715
|
+
(doc33) => ({
|
|
13716
|
+
id: doc33.id,
|
|
13717
|
+
...doc33.data()
|
|
13084
13718
|
})
|
|
13085
13719
|
);
|
|
13086
13720
|
}
|
|
@@ -13096,8 +13730,8 @@ var SubcategoryService = class extends BaseService {
|
|
|
13096
13730
|
...subcategory,
|
|
13097
13731
|
updatedAt: /* @__PURE__ */ new Date()
|
|
13098
13732
|
};
|
|
13099
|
-
const docRef = (0,
|
|
13100
|
-
await (0,
|
|
13733
|
+
const docRef = (0, import_firestore44.doc)(this.getSubcategoriesRef(categoryId), subcategoryId);
|
|
13734
|
+
await (0, import_firestore44.updateDoc)(docRef, updateData);
|
|
13101
13735
|
return this.getById(categoryId, subcategoryId);
|
|
13102
13736
|
}
|
|
13103
13737
|
/**
|
|
@@ -13115,8 +13749,8 @@ var SubcategoryService = class extends BaseService {
|
|
|
13115
13749
|
* @returns Podkategorija ili null ako ne postoji
|
|
13116
13750
|
*/
|
|
13117
13751
|
async getById(categoryId, subcategoryId) {
|
|
13118
|
-
const docRef = (0,
|
|
13119
|
-
const docSnap = await (0,
|
|
13752
|
+
const docRef = (0, import_firestore44.doc)(this.getSubcategoriesRef(categoryId), subcategoryId);
|
|
13753
|
+
const docSnap = await (0, import_firestore44.getDoc)(docRef);
|
|
13120
13754
|
if (!docSnap.exists()) return null;
|
|
13121
13755
|
return {
|
|
13122
13756
|
id: docSnap.id,
|
|
@@ -13126,7 +13760,7 @@ var SubcategoryService = class extends BaseService {
|
|
|
13126
13760
|
};
|
|
13127
13761
|
|
|
13128
13762
|
// src/backoffice/services/technology.service.ts
|
|
13129
|
-
var
|
|
13763
|
+
var import_firestore45 = require("firebase/firestore");
|
|
13130
13764
|
var DEFAULT_CERTIFICATION_REQUIREMENT = {
|
|
13131
13765
|
minimumLevel: "aesthetician" /* AESTHETICIAN */,
|
|
13132
13766
|
requiredSpecialties: []
|
|
@@ -13136,7 +13770,7 @@ var TechnologyService = class extends BaseService {
|
|
|
13136
13770
|
* Vraća referencu na Firestore kolekciju tehnologija
|
|
13137
13771
|
*/
|
|
13138
13772
|
getTechnologiesRef() {
|
|
13139
|
-
return (0,
|
|
13773
|
+
return (0, import_firestore45.collection)(this.db, TECHNOLOGIES_COLLECTION);
|
|
13140
13774
|
}
|
|
13141
13775
|
/**
|
|
13142
13776
|
* Kreira novu tehnologiju
|
|
@@ -13159,7 +13793,7 @@ var TechnologyService = class extends BaseService {
|
|
|
13159
13793
|
benefits: technology.benefits || [],
|
|
13160
13794
|
certificationRequirement: technology.certificationRequirement || DEFAULT_CERTIFICATION_REQUIREMENT
|
|
13161
13795
|
};
|
|
13162
|
-
const docRef = await (0,
|
|
13796
|
+
const docRef = await (0, import_firestore45.addDoc)(this.getTechnologiesRef(), newTechnology);
|
|
13163
13797
|
return { id: docRef.id, ...newTechnology };
|
|
13164
13798
|
}
|
|
13165
13799
|
/**
|
|
@@ -13167,12 +13801,12 @@ var TechnologyService = class extends BaseService {
|
|
|
13167
13801
|
* @returns Lista aktivnih tehnologija
|
|
13168
13802
|
*/
|
|
13169
13803
|
async getAll() {
|
|
13170
|
-
const q = (0,
|
|
13171
|
-
const snapshot = await (0,
|
|
13804
|
+
const q = (0, import_firestore45.query)(this.getTechnologiesRef(), (0, import_firestore45.where)("isActive", "==", true));
|
|
13805
|
+
const snapshot = await (0, import_firestore45.getDocs)(q);
|
|
13172
13806
|
return snapshot.docs.map(
|
|
13173
|
-
(
|
|
13174
|
-
id:
|
|
13175
|
-
...
|
|
13807
|
+
(doc33) => ({
|
|
13808
|
+
id: doc33.id,
|
|
13809
|
+
...doc33.data()
|
|
13176
13810
|
})
|
|
13177
13811
|
);
|
|
13178
13812
|
}
|
|
@@ -13182,16 +13816,16 @@ var TechnologyService = class extends BaseService {
|
|
|
13182
13816
|
* @returns Lista aktivnih tehnologija
|
|
13183
13817
|
*/
|
|
13184
13818
|
async getAllByFamily(family) {
|
|
13185
|
-
const q = (0,
|
|
13819
|
+
const q = (0, import_firestore45.query)(
|
|
13186
13820
|
this.getTechnologiesRef(),
|
|
13187
|
-
(0,
|
|
13188
|
-
(0,
|
|
13821
|
+
(0, import_firestore45.where)("isActive", "==", true),
|
|
13822
|
+
(0, import_firestore45.where)("family", "==", family)
|
|
13189
13823
|
);
|
|
13190
|
-
const snapshot = await (0,
|
|
13824
|
+
const snapshot = await (0, import_firestore45.getDocs)(q);
|
|
13191
13825
|
return snapshot.docs.map(
|
|
13192
|
-
(
|
|
13193
|
-
id:
|
|
13194
|
-
...
|
|
13826
|
+
(doc33) => ({
|
|
13827
|
+
id: doc33.id,
|
|
13828
|
+
...doc33.data()
|
|
13195
13829
|
})
|
|
13196
13830
|
);
|
|
13197
13831
|
}
|
|
@@ -13201,16 +13835,16 @@ var TechnologyService = class extends BaseService {
|
|
|
13201
13835
|
* @returns Lista aktivnih tehnologija
|
|
13202
13836
|
*/
|
|
13203
13837
|
async getAllByCategoryId(categoryId) {
|
|
13204
|
-
const q = (0,
|
|
13838
|
+
const q = (0, import_firestore45.query)(
|
|
13205
13839
|
this.getTechnologiesRef(),
|
|
13206
|
-
(0,
|
|
13207
|
-
(0,
|
|
13840
|
+
(0, import_firestore45.where)("isActive", "==", true),
|
|
13841
|
+
(0, import_firestore45.where)("categoryId", "==", categoryId)
|
|
13208
13842
|
);
|
|
13209
|
-
const snapshot = await (0,
|
|
13843
|
+
const snapshot = await (0, import_firestore45.getDocs)(q);
|
|
13210
13844
|
return snapshot.docs.map(
|
|
13211
|
-
(
|
|
13212
|
-
id:
|
|
13213
|
-
...
|
|
13845
|
+
(doc33) => ({
|
|
13846
|
+
id: doc33.id,
|
|
13847
|
+
...doc33.data()
|
|
13214
13848
|
})
|
|
13215
13849
|
);
|
|
13216
13850
|
}
|
|
@@ -13220,16 +13854,16 @@ var TechnologyService = class extends BaseService {
|
|
|
13220
13854
|
* @returns Lista aktivnih tehnologija
|
|
13221
13855
|
*/
|
|
13222
13856
|
async getAllBySubcategoryId(subcategoryId) {
|
|
13223
|
-
const q = (0,
|
|
13857
|
+
const q = (0, import_firestore45.query)(
|
|
13224
13858
|
this.getTechnologiesRef(),
|
|
13225
|
-
(0,
|
|
13226
|
-
(0,
|
|
13859
|
+
(0, import_firestore45.where)("isActive", "==", true),
|
|
13860
|
+
(0, import_firestore45.where)("subcategoryId", "==", subcategoryId)
|
|
13227
13861
|
);
|
|
13228
|
-
const snapshot = await (0,
|
|
13862
|
+
const snapshot = await (0, import_firestore45.getDocs)(q);
|
|
13229
13863
|
return snapshot.docs.map(
|
|
13230
|
-
(
|
|
13231
|
-
id:
|
|
13232
|
-
...
|
|
13864
|
+
(doc33) => ({
|
|
13865
|
+
id: doc33.id,
|
|
13866
|
+
...doc33.data()
|
|
13233
13867
|
})
|
|
13234
13868
|
);
|
|
13235
13869
|
}
|
|
@@ -13244,8 +13878,8 @@ var TechnologyService = class extends BaseService {
|
|
|
13244
13878
|
...technology,
|
|
13245
13879
|
updatedAt: /* @__PURE__ */ new Date()
|
|
13246
13880
|
};
|
|
13247
|
-
const docRef = (0,
|
|
13248
|
-
await (0,
|
|
13881
|
+
const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
|
|
13882
|
+
await (0, import_firestore45.updateDoc)(docRef, updateData);
|
|
13249
13883
|
return this.getById(technologyId);
|
|
13250
13884
|
}
|
|
13251
13885
|
/**
|
|
@@ -13263,8 +13897,8 @@ var TechnologyService = class extends BaseService {
|
|
|
13263
13897
|
* @returns Tehnologija ili null ako ne postoji
|
|
13264
13898
|
*/
|
|
13265
13899
|
async getById(technologyId) {
|
|
13266
|
-
const docRef = (0,
|
|
13267
|
-
const docSnap = await (0,
|
|
13900
|
+
const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
|
|
13901
|
+
const docSnap = await (0, import_firestore45.getDoc)(docRef);
|
|
13268
13902
|
if (!docSnap.exists()) return null;
|
|
13269
13903
|
return {
|
|
13270
13904
|
id: docSnap.id,
|
|
@@ -13278,10 +13912,10 @@ var TechnologyService = class extends BaseService {
|
|
|
13278
13912
|
* @returns Ažurirana tehnologija sa novim zahtevom
|
|
13279
13913
|
*/
|
|
13280
13914
|
async addRequirement(technologyId, requirement) {
|
|
13281
|
-
const docRef = (0,
|
|
13915
|
+
const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
|
|
13282
13916
|
const requirementType = requirement.type === "pre" ? "requirements.pre" : "requirements.post";
|
|
13283
|
-
await (0,
|
|
13284
|
-
[requirementType]: (0,
|
|
13917
|
+
await (0, import_firestore45.updateDoc)(docRef, {
|
|
13918
|
+
[requirementType]: (0, import_firestore45.arrayUnion)(requirement),
|
|
13285
13919
|
updatedAt: /* @__PURE__ */ new Date()
|
|
13286
13920
|
});
|
|
13287
13921
|
return this.getById(technologyId);
|
|
@@ -13293,10 +13927,10 @@ var TechnologyService = class extends BaseService {
|
|
|
13293
13927
|
* @returns Ažurirana tehnologija bez uklonjenog zahteva
|
|
13294
13928
|
*/
|
|
13295
13929
|
async removeRequirement(technologyId, requirement) {
|
|
13296
|
-
const docRef = (0,
|
|
13930
|
+
const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
|
|
13297
13931
|
const requirementType = requirement.type === "pre" ? "requirements.pre" : "requirements.post";
|
|
13298
|
-
await (0,
|
|
13299
|
-
[requirementType]: (0,
|
|
13932
|
+
await (0, import_firestore45.updateDoc)(docRef, {
|
|
13933
|
+
[requirementType]: (0, import_firestore45.arrayRemove)(requirement),
|
|
13300
13934
|
updatedAt: /* @__PURE__ */ new Date()
|
|
13301
13935
|
});
|
|
13302
13936
|
return this.getById(technologyId);
|
|
@@ -13333,9 +13967,9 @@ var TechnologyService = class extends BaseService {
|
|
|
13333
13967
|
* @returns Ažurirana tehnologija
|
|
13334
13968
|
*/
|
|
13335
13969
|
async addBlockingCondition(technologyId, condition) {
|
|
13336
|
-
const docRef = (0,
|
|
13337
|
-
await (0,
|
|
13338
|
-
blockingConditions: (0,
|
|
13970
|
+
const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
|
|
13971
|
+
await (0, import_firestore45.updateDoc)(docRef, {
|
|
13972
|
+
blockingConditions: (0, import_firestore45.arrayUnion)(condition),
|
|
13339
13973
|
updatedAt: /* @__PURE__ */ new Date()
|
|
13340
13974
|
});
|
|
13341
13975
|
return this.getById(technologyId);
|
|
@@ -13347,9 +13981,9 @@ var TechnologyService = class extends BaseService {
|
|
|
13347
13981
|
* @returns Ažurirana tehnologija
|
|
13348
13982
|
*/
|
|
13349
13983
|
async removeBlockingCondition(technologyId, condition) {
|
|
13350
|
-
const docRef = (0,
|
|
13351
|
-
await (0,
|
|
13352
|
-
blockingConditions: (0,
|
|
13984
|
+
const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
|
|
13985
|
+
await (0, import_firestore45.updateDoc)(docRef, {
|
|
13986
|
+
blockingConditions: (0, import_firestore45.arrayRemove)(condition),
|
|
13353
13987
|
updatedAt: /* @__PURE__ */ new Date()
|
|
13354
13988
|
});
|
|
13355
13989
|
return this.getById(technologyId);
|
|
@@ -13361,9 +13995,9 @@ var TechnologyService = class extends BaseService {
|
|
|
13361
13995
|
* @returns Ažurirana tehnologija
|
|
13362
13996
|
*/
|
|
13363
13997
|
async addContraindication(technologyId, contraindication) {
|
|
13364
|
-
const docRef = (0,
|
|
13365
|
-
await (0,
|
|
13366
|
-
contraindications: (0,
|
|
13998
|
+
const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
|
|
13999
|
+
await (0, import_firestore45.updateDoc)(docRef, {
|
|
14000
|
+
contraindications: (0, import_firestore45.arrayUnion)(contraindication),
|
|
13367
14001
|
updatedAt: /* @__PURE__ */ new Date()
|
|
13368
14002
|
});
|
|
13369
14003
|
return this.getById(technologyId);
|
|
@@ -13375,9 +14009,9 @@ var TechnologyService = class extends BaseService {
|
|
|
13375
14009
|
* @returns Ažurirana tehnologija
|
|
13376
14010
|
*/
|
|
13377
14011
|
async removeContraindication(technologyId, contraindication) {
|
|
13378
|
-
const docRef = (0,
|
|
13379
|
-
await (0,
|
|
13380
|
-
contraindications: (0,
|
|
14012
|
+
const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
|
|
14013
|
+
await (0, import_firestore45.updateDoc)(docRef, {
|
|
14014
|
+
contraindications: (0, import_firestore45.arrayRemove)(contraindication),
|
|
13381
14015
|
updatedAt: /* @__PURE__ */ new Date()
|
|
13382
14016
|
});
|
|
13383
14017
|
return this.getById(technologyId);
|
|
@@ -13389,9 +14023,9 @@ var TechnologyService = class extends BaseService {
|
|
|
13389
14023
|
* @returns Ažurirana tehnologija
|
|
13390
14024
|
*/
|
|
13391
14025
|
async addBenefit(technologyId, benefit) {
|
|
13392
|
-
const docRef = (0,
|
|
13393
|
-
await (0,
|
|
13394
|
-
benefits: (0,
|
|
14026
|
+
const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
|
|
14027
|
+
await (0, import_firestore45.updateDoc)(docRef, {
|
|
14028
|
+
benefits: (0, import_firestore45.arrayUnion)(benefit),
|
|
13395
14029
|
updatedAt: /* @__PURE__ */ new Date()
|
|
13396
14030
|
});
|
|
13397
14031
|
return this.getById(technologyId);
|
|
@@ -13403,9 +14037,9 @@ var TechnologyService = class extends BaseService {
|
|
|
13403
14037
|
* @returns Ažurirana tehnologija
|
|
13404
14038
|
*/
|
|
13405
14039
|
async removeBenefit(technologyId, benefit) {
|
|
13406
|
-
const docRef = (0,
|
|
13407
|
-
await (0,
|
|
13408
|
-
benefits: (0,
|
|
14040
|
+
const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
|
|
14041
|
+
await (0, import_firestore45.updateDoc)(docRef, {
|
|
14042
|
+
benefits: (0, import_firestore45.arrayRemove)(benefit),
|
|
13409
14043
|
updatedAt: /* @__PURE__ */ new Date()
|
|
13410
14044
|
});
|
|
13411
14045
|
return this.getById(technologyId);
|
|
@@ -13444,8 +14078,8 @@ var TechnologyService = class extends BaseService {
|
|
|
13444
14078
|
* @returns Ažurirana tehnologija
|
|
13445
14079
|
*/
|
|
13446
14080
|
async updateCertificationRequirement(technologyId, certificationRequirement) {
|
|
13447
|
-
const docRef = (0,
|
|
13448
|
-
await (0,
|
|
14081
|
+
const docRef = (0, import_firestore45.doc)(this.getTechnologiesRef(), technologyId);
|
|
14082
|
+
await (0, import_firestore45.updateDoc)(docRef, {
|
|
13449
14083
|
certificationRequirement,
|
|
13450
14084
|
updatedAt: /* @__PURE__ */ new Date()
|
|
13451
14085
|
});
|
|
@@ -13545,7 +14179,7 @@ var TechnologyService = class extends BaseService {
|
|
|
13545
14179
|
};
|
|
13546
14180
|
|
|
13547
14181
|
// src/backoffice/services/product.service.ts
|
|
13548
|
-
var
|
|
14182
|
+
var import_firestore46 = require("firebase/firestore");
|
|
13549
14183
|
|
|
13550
14184
|
// src/backoffice/types/product.types.ts
|
|
13551
14185
|
var PRODUCTS_COLLECTION = "products";
|
|
@@ -13558,7 +14192,7 @@ var ProductService = class extends BaseService {
|
|
|
13558
14192
|
* @returns Firestore collection reference
|
|
13559
14193
|
*/
|
|
13560
14194
|
getProductsRef(technologyId) {
|
|
13561
|
-
return (0,
|
|
14195
|
+
return (0, import_firestore46.collection)(
|
|
13562
14196
|
this.db,
|
|
13563
14197
|
TECHNOLOGIES_COLLECTION,
|
|
13564
14198
|
technologyId,
|
|
@@ -13578,7 +14212,7 @@ var ProductService = class extends BaseService {
|
|
|
13578
14212
|
updatedAt: now,
|
|
13579
14213
|
isActive: true
|
|
13580
14214
|
};
|
|
13581
|
-
const productRef = await (0,
|
|
14215
|
+
const productRef = await (0, import_firestore46.addDoc)(
|
|
13582
14216
|
this.getProductsRef(technologyId),
|
|
13583
14217
|
newProduct
|
|
13584
14218
|
);
|
|
@@ -13588,15 +14222,15 @@ var ProductService = class extends BaseService {
|
|
|
13588
14222
|
* Gets all products for a technology
|
|
13589
14223
|
*/
|
|
13590
14224
|
async getAllByTechnology(technologyId) {
|
|
13591
|
-
const q = (0,
|
|
14225
|
+
const q = (0, import_firestore46.query)(
|
|
13592
14226
|
this.getProductsRef(technologyId),
|
|
13593
|
-
(0,
|
|
14227
|
+
(0, import_firestore46.where)("isActive", "==", true)
|
|
13594
14228
|
);
|
|
13595
|
-
const snapshot = await (0,
|
|
14229
|
+
const snapshot = await (0, import_firestore46.getDocs)(q);
|
|
13596
14230
|
return snapshot.docs.map(
|
|
13597
|
-
(
|
|
13598
|
-
id:
|
|
13599
|
-
...
|
|
14231
|
+
(doc33) => ({
|
|
14232
|
+
id: doc33.id,
|
|
14233
|
+
...doc33.data()
|
|
13600
14234
|
})
|
|
13601
14235
|
);
|
|
13602
14236
|
}
|
|
@@ -13604,21 +14238,21 @@ var ProductService = class extends BaseService {
|
|
|
13604
14238
|
* Gets all products for a brand by filtering through all technologies
|
|
13605
14239
|
*/
|
|
13606
14240
|
async getAllByBrand(brandId) {
|
|
13607
|
-
const allTechnologiesRef = (0,
|
|
13608
|
-
const technologiesSnapshot = await (0,
|
|
14241
|
+
const allTechnologiesRef = (0, import_firestore46.collection)(this.db, TECHNOLOGIES_COLLECTION);
|
|
14242
|
+
const technologiesSnapshot = await (0, import_firestore46.getDocs)(allTechnologiesRef);
|
|
13609
14243
|
const products = [];
|
|
13610
14244
|
for (const techDoc of technologiesSnapshot.docs) {
|
|
13611
|
-
const q = (0,
|
|
14245
|
+
const q = (0, import_firestore46.query)(
|
|
13612
14246
|
this.getProductsRef(techDoc.id),
|
|
13613
|
-
(0,
|
|
13614
|
-
(0,
|
|
14247
|
+
(0, import_firestore46.where)("brandId", "==", brandId),
|
|
14248
|
+
(0, import_firestore46.where)("isActive", "==", true)
|
|
13615
14249
|
);
|
|
13616
|
-
const snapshot = await (0,
|
|
14250
|
+
const snapshot = await (0, import_firestore46.getDocs)(q);
|
|
13617
14251
|
products.push(
|
|
13618
14252
|
...snapshot.docs.map(
|
|
13619
|
-
(
|
|
13620
|
-
id:
|
|
13621
|
-
...
|
|
14253
|
+
(doc33) => ({
|
|
14254
|
+
id: doc33.id,
|
|
14255
|
+
...doc33.data()
|
|
13622
14256
|
})
|
|
13623
14257
|
)
|
|
13624
14258
|
);
|
|
@@ -13633,8 +14267,8 @@ var ProductService = class extends BaseService {
|
|
|
13633
14267
|
...product,
|
|
13634
14268
|
updatedAt: /* @__PURE__ */ new Date()
|
|
13635
14269
|
};
|
|
13636
|
-
const docRef = (0,
|
|
13637
|
-
await (0,
|
|
14270
|
+
const docRef = (0, import_firestore46.doc)(this.getProductsRef(technologyId), productId);
|
|
14271
|
+
await (0, import_firestore46.updateDoc)(docRef, updateData);
|
|
13638
14272
|
return this.getById(technologyId, productId);
|
|
13639
14273
|
}
|
|
13640
14274
|
/**
|
|
@@ -13649,8 +14283,8 @@ var ProductService = class extends BaseService {
|
|
|
13649
14283
|
* Gets a product by ID
|
|
13650
14284
|
*/
|
|
13651
14285
|
async getById(technologyId, productId) {
|
|
13652
|
-
const docRef = (0,
|
|
13653
|
-
const docSnap = await (0,
|
|
14286
|
+
const docRef = (0, import_firestore46.doc)(this.getProductsRef(technologyId), productId);
|
|
14287
|
+
const docSnap = await (0, import_firestore46.getDoc)(docRef);
|
|
13654
14288
|
if (!docSnap.exists()) return null;
|
|
13655
14289
|
return {
|
|
13656
14290
|
id: docSnap.id,
|
|
@@ -13679,14 +14313,14 @@ var baseNotificationSchema = import_zod24.z.object({
|
|
|
13679
14313
|
userRole: import_zod24.z.nativeEnum(UserRole)
|
|
13680
14314
|
});
|
|
13681
14315
|
var preRequirementNotificationSchema = baseNotificationSchema.extend({
|
|
13682
|
-
notificationType: import_zod24.z.literal("
|
|
14316
|
+
notificationType: import_zod24.z.literal("requirementInstructionDue" /* REQUIREMENT_INSTRUCTION_DUE */),
|
|
13683
14317
|
treatmentId: import_zod24.z.string(),
|
|
13684
14318
|
requirements: import_zod24.z.array(import_zod24.z.string()),
|
|
13685
14319
|
deadline: import_zod24.z.any()
|
|
13686
14320
|
// Timestamp
|
|
13687
14321
|
});
|
|
13688
14322
|
var postRequirementNotificationSchema = baseNotificationSchema.extend({
|
|
13689
|
-
notificationType: import_zod24.z.literal("
|
|
14323
|
+
notificationType: import_zod24.z.literal("requirementInstructionDue" /* REQUIREMENT_INSTRUCTION_DUE */),
|
|
13690
14324
|
treatmentId: import_zod24.z.string(),
|
|
13691
14325
|
requirements: import_zod24.z.array(import_zod24.z.string()),
|
|
13692
14326
|
deadline: import_zod24.z.any()
|
|
@@ -13701,7 +14335,7 @@ var appointmentReminderNotificationSchema = baseNotificationSchema.extend({
|
|
|
13701
14335
|
doctorName: import_zod24.z.string()
|
|
13702
14336
|
});
|
|
13703
14337
|
var appointmentNotificationSchema = baseNotificationSchema.extend({
|
|
13704
|
-
notificationType: import_zod24.z.literal("
|
|
14338
|
+
notificationType: import_zod24.z.literal("appointmentStatusChange" /* APPOINTMENT_STATUS_CHANGE */),
|
|
13705
14339
|
appointmentId: import_zod24.z.string(),
|
|
13706
14340
|
appointmentStatus: import_zod24.z.string(),
|
|
13707
14341
|
previousStatus: import_zod24.z.string(),
|
|
@@ -13798,9 +14432,13 @@ var RequirementType = /* @__PURE__ */ ((RequirementType2) => {
|
|
|
13798
14432
|
PATIENT_LOCATION_INFO_COLLECTION,
|
|
13799
14433
|
PATIENT_MEDICAL_HISTORY_COLLECTION,
|
|
13800
14434
|
PATIENT_MEDICAL_INFO_COLLECTION,
|
|
14435
|
+
PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME,
|
|
13801
14436
|
PATIENT_SENSITIVE_INFO_COLLECTION,
|
|
13802
14437
|
PRACTITIONERS_COLLECTION,
|
|
13803
14438
|
PROCEDURES_COLLECTION,
|
|
14439
|
+
PatientInstructionStatus,
|
|
14440
|
+
PatientRequirementOverallStatus,
|
|
14441
|
+
PatientRequirementsService,
|
|
13804
14442
|
PatientService,
|
|
13805
14443
|
PaymentStatus,
|
|
13806
14444
|
PracticeType,
|
|
@@ -13865,6 +14503,7 @@ var RequirementType = /* @__PURE__ */ ((RequirementType2) => {
|
|
|
13865
14503
|
createDefaultClinicGroupSchema,
|
|
13866
14504
|
createDocumentTemplateSchema,
|
|
13867
14505
|
createDraftPractitionerSchema,
|
|
14506
|
+
createFilledDocumentDataSchema,
|
|
13868
14507
|
createPatientLocationInfoSchema,
|
|
13869
14508
|
createPatientMedicalInfoSchema,
|
|
13870
14509
|
createPatientProfileSchema,
|
|
@@ -13880,6 +14519,8 @@ var RequirementType = /* @__PURE__ */ ((RequirementType2) => {
|
|
|
13880
14519
|
documentTemplateSchema,
|
|
13881
14520
|
emailSchema,
|
|
13882
14521
|
emergencyContactSchema,
|
|
14522
|
+
filledDocumentSchema,
|
|
14523
|
+
filledDocumentStatusSchema,
|
|
13883
14524
|
gamificationSchema,
|
|
13884
14525
|
getFirebaseApp,
|
|
13885
14526
|
getFirebaseAuth,
|
|
@@ -13929,6 +14570,7 @@ var RequirementType = /* @__PURE__ */ ((RequirementType2) => {
|
|
|
13929
14570
|
updateClinicSchema,
|
|
13930
14571
|
updateContraindicationSchema,
|
|
13931
14572
|
updateDocumentTemplateSchema,
|
|
14573
|
+
updateFilledDocumentDataSchema,
|
|
13932
14574
|
updateMedicationSchema,
|
|
13933
14575
|
updatePatientMedicalInfoSchema,
|
|
13934
14576
|
updateVitalStatsSchema,
|