@blackcode_sa/metaestetics-api 1.11.1 → 1.11.2
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 +324 -330
- package/dist/admin/index.d.ts +324 -330
- package/dist/backoffice/index.d.mts +67 -283
- package/dist/backoffice/index.d.ts +67 -283
- package/dist/backoffice/index.js +6 -114
- package/dist/backoffice/index.mjs +6 -112
- package/dist/index.d.mts +3037 -3100
- package/dist/index.d.ts +3037 -3100
- package/dist/index.js +129 -379
- package/dist/index.mjs +130 -379
- package/package.json +1 -1
- package/src/backoffice/expo-safe/index.ts +0 -2
- package/src/backoffice/services/__tests__/brand.service.test.ts +196 -0
- package/src/backoffice/services/__tests__/category.service.test.ts +201 -0
- package/src/backoffice/services/__tests__/product.service.test.ts +358 -0
- package/src/backoffice/services/__tests__/requirement.service.test.ts +226 -0
- package/src/backoffice/services/__tests__/subcategory.service.test.ts +181 -0
- package/src/backoffice/services/__tests__/technology.service.test.ts +1097 -0
- package/src/backoffice/services/technology.service.ts +10 -122
- package/src/backoffice/types/index.ts +0 -1
- package/src/backoffice/types/product.types.ts +1 -3
- package/src/backoffice/types/technology.types.ts +4 -4
- package/src/backoffice/validations/schemas.ts +9 -35
- package/src/services/appointment/appointment.service.ts +5 -0
- package/src/services/appointment/utils/appointment.utils.ts +113 -124
- package/src/services/procedure/procedure.service.ts +234 -434
- package/src/types/appointment/index.ts +37 -43
- package/src/types/clinic/index.ts +6 -1
- package/src/types/patient/medical-info.types.ts +3 -3
- package/src/types/procedure/index.ts +17 -20
- package/src/validations/appointment.schema.ts +118 -170
- package/src/validations/clinic.schema.ts +6 -1
- package/src/validations/patient/medical-info.schema.ts +2 -7
- package/src/backoffice/services/README.md +0 -40
- package/src/backoffice/services/constants.service.ts +0 -268
- package/src/backoffice/types/admin-constants.types.ts +0 -69
|
@@ -14,8 +14,8 @@ import {
|
|
|
14
14
|
import { Technology, TECHNOLOGIES_COLLECTION } from "../types/technology.types";
|
|
15
15
|
import { Requirement, RequirementType } from "../types/requirement.types";
|
|
16
16
|
import { BlockingCondition } from "../types/static/blocking-condition.types";
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
17
|
+
import { Contraindication } from "../types/static/contraindication.types";
|
|
18
|
+
import { TreatmentBenefit } from "../types/static/treatment-benefit.types";
|
|
19
19
|
import {
|
|
20
20
|
CertificationLevel,
|
|
21
21
|
CertificationSpecialty,
|
|
@@ -346,21 +346,12 @@ export class TechnologyService extends BaseService {
|
|
|
346
346
|
*/
|
|
347
347
|
async addContraindication(
|
|
348
348
|
technologyId: string,
|
|
349
|
-
contraindication:
|
|
349
|
+
contraindication: Contraindication
|
|
350
350
|
) {
|
|
351
351
|
const docRef = doc(this.getTechnologiesRef(), technologyId);
|
|
352
|
-
const technology = await this.getById(technologyId);
|
|
353
|
-
if (!technology) {
|
|
354
|
-
throw new Error(`Technology with id ${technologyId} not found`);
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
const existingContraindications = technology.contraindications || [];
|
|
358
|
-
if (existingContraindications.some((c) => c.id === contraindication.id)) {
|
|
359
|
-
return technology; // Already exists, do nothing
|
|
360
|
-
}
|
|
361
352
|
|
|
362
353
|
await updateDoc(docRef, {
|
|
363
|
-
contraindications:
|
|
354
|
+
contraindications: arrayUnion(contraindication),
|
|
364
355
|
updatedAt: new Date(),
|
|
365
356
|
});
|
|
366
357
|
|
|
@@ -375,62 +366,12 @@ export class TechnologyService extends BaseService {
|
|
|
375
366
|
*/
|
|
376
367
|
async removeContraindication(
|
|
377
368
|
technologyId: string,
|
|
378
|
-
contraindication:
|
|
369
|
+
contraindication: Contraindication
|
|
379
370
|
) {
|
|
380
371
|
const docRef = doc(this.getTechnologiesRef(), technologyId);
|
|
381
|
-
const technology = await this.getById(technologyId);
|
|
382
|
-
if (!technology) {
|
|
383
|
-
throw new Error(`Technology with id ${technologyId} not found`);
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
const updatedContraindications = (
|
|
387
|
-
technology.contraindications || []
|
|
388
|
-
).filter((c) => c.id !== contraindication.id);
|
|
389
|
-
|
|
390
|
-
await updateDoc(docRef, {
|
|
391
|
-
contraindications: updatedContraindications,
|
|
392
|
-
updatedAt: new Date(),
|
|
393
|
-
});
|
|
394
|
-
|
|
395
|
-
return this.getById(technologyId);
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
/**
|
|
399
|
-
* Updates an existing contraindication in a technology's list.
|
|
400
|
-
* If the contraindication does not exist, it will not be added.
|
|
401
|
-
* @param technologyId - ID of the technology
|
|
402
|
-
* @param contraindication - The updated contraindication object
|
|
403
|
-
* @returns The updated technology
|
|
404
|
-
*/
|
|
405
|
-
async updateContraindication(
|
|
406
|
-
technologyId: string,
|
|
407
|
-
contraindication: ContraindicationDynamic
|
|
408
|
-
) {
|
|
409
|
-
const docRef = doc(this.getTechnologiesRef(), technologyId);
|
|
410
|
-
const technology = await this.getById(technologyId);
|
|
411
|
-
if (!technology) {
|
|
412
|
-
throw new Error(`Technology with id ${technologyId} not found`);
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
const contraindications = technology.contraindications || [];
|
|
416
|
-
const index = contraindications.findIndex(
|
|
417
|
-
(c) => c.id === contraindication.id
|
|
418
|
-
);
|
|
419
|
-
|
|
420
|
-
if (index === -1) {
|
|
421
|
-
// If contraindication doesn't exist, do not update
|
|
422
|
-
// Consider throwing an error if this is an unexpected state
|
|
423
|
-
console.warn(
|
|
424
|
-
`Contraindication with id ${contraindication.id} not found for technology ${technologyId}. No update performed.`
|
|
425
|
-
);
|
|
426
|
-
return technology;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
const updatedContraindications = [...contraindications];
|
|
430
|
-
updatedContraindications[index] = contraindication;
|
|
431
372
|
|
|
432
373
|
await updateDoc(docRef, {
|
|
433
|
-
contraindications:
|
|
374
|
+
contraindications: arrayRemove(contraindication),
|
|
434
375
|
updatedAt: new Date(),
|
|
435
376
|
});
|
|
436
377
|
|
|
@@ -443,20 +384,11 @@ export class TechnologyService extends BaseService {
|
|
|
443
384
|
* @param benefit - Benefit koji se dodaje
|
|
444
385
|
* @returns Ažurirana tehnologija
|
|
445
386
|
*/
|
|
446
|
-
async addBenefit(technologyId: string, benefit:
|
|
387
|
+
async addBenefit(technologyId: string, benefit: TreatmentBenefit) {
|
|
447
388
|
const docRef = doc(this.getTechnologiesRef(), technologyId);
|
|
448
|
-
const technology = await this.getById(technologyId);
|
|
449
|
-
if (!technology) {
|
|
450
|
-
throw new Error(`Technology with id ${technologyId} not found`);
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
const existingBenefits = technology.benefits || [];
|
|
454
|
-
if (existingBenefits.some((b) => b.id === benefit.id)) {
|
|
455
|
-
return technology; // Already exists, do nothing
|
|
456
|
-
}
|
|
457
389
|
|
|
458
390
|
await updateDoc(docRef, {
|
|
459
|
-
benefits:
|
|
391
|
+
benefits: arrayUnion(benefit),
|
|
460
392
|
updatedAt: new Date(),
|
|
461
393
|
});
|
|
462
394
|
|
|
@@ -469,55 +401,11 @@ export class TechnologyService extends BaseService {
|
|
|
469
401
|
* @param benefit - Benefit koji se uklanja
|
|
470
402
|
* @returns Ažurirana tehnologija
|
|
471
403
|
*/
|
|
472
|
-
async removeBenefit(technologyId: string, benefit:
|
|
404
|
+
async removeBenefit(technologyId: string, benefit: TreatmentBenefit) {
|
|
473
405
|
const docRef = doc(this.getTechnologiesRef(), technologyId);
|
|
474
|
-
const technology = await this.getById(technologyId);
|
|
475
|
-
if (!technology) {
|
|
476
|
-
throw new Error(`Technology with id ${technologyId} not found`);
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
const updatedBenefits = (technology.benefits || []).filter(
|
|
480
|
-
(b) => b.id !== benefit.id
|
|
481
|
-
);
|
|
482
|
-
|
|
483
|
-
await updateDoc(docRef, {
|
|
484
|
-
benefits: updatedBenefits,
|
|
485
|
-
updatedAt: new Date(),
|
|
486
|
-
});
|
|
487
|
-
|
|
488
|
-
return this.getById(technologyId);
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
/**
|
|
492
|
-
* Updates an existing benefit in a technology's list.
|
|
493
|
-
* If the benefit does not exist, it will not be added.
|
|
494
|
-
* @param technologyId - ID of the technology
|
|
495
|
-
* @param benefit - The updated benefit object
|
|
496
|
-
* @returns The updated technology
|
|
497
|
-
*/
|
|
498
|
-
async updateBenefit(technologyId: string, benefit: TreatmentBenefitDynamic) {
|
|
499
|
-
const docRef = doc(this.getTechnologiesRef(), technologyId);
|
|
500
|
-
const technology = await this.getById(technologyId);
|
|
501
|
-
if (!technology) {
|
|
502
|
-
throw new Error(`Technology with id ${technologyId} not found`);
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
const benefits = technology.benefits || [];
|
|
506
|
-
const index = benefits.findIndex((b) => b.id === benefit.id);
|
|
507
|
-
|
|
508
|
-
if (index === -1) {
|
|
509
|
-
// If benefit doesn't exist, do not update
|
|
510
|
-
console.warn(
|
|
511
|
-
`Benefit with id ${benefit.id} not found for technology ${technologyId}. No update performed.`
|
|
512
|
-
);
|
|
513
|
-
return technology;
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
const updatedBenefits = [...benefits];
|
|
517
|
-
updatedBenefits[index] = benefit;
|
|
518
406
|
|
|
519
407
|
await updateDoc(docRef, {
|
|
520
|
-
benefits:
|
|
408
|
+
benefits: arrayRemove(benefit),
|
|
521
409
|
updatedAt: new Date(),
|
|
522
410
|
});
|
|
523
411
|
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import type { ContraindicationDynamic } from "./admin-constants.types";
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* Product used in procedures
|
|
5
3
|
* Can be consumables, equipment, or any other product needed for performing procedures
|
|
@@ -35,7 +33,7 @@ export interface Product {
|
|
|
35
33
|
dosage?: string;
|
|
36
34
|
composition?: string;
|
|
37
35
|
indications?: string[];
|
|
38
|
-
contraindications?:
|
|
36
|
+
contraindications?: string[];
|
|
39
37
|
}
|
|
40
38
|
|
|
41
39
|
/**
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Requirement } from "./requirement.types";
|
|
2
2
|
import { BlockingCondition } from "./static/blocking-condition.types";
|
|
3
|
+
import { Contraindication } from "./static/contraindication.types";
|
|
4
|
+
import { TreatmentBenefit } from "./static/treatment-benefit.types";
|
|
3
5
|
import { CertificationRequirement } from "./static/certification.types";
|
|
4
6
|
import { DocumentTemplate } from "../../types/documentation-templates";
|
|
5
7
|
import { ProcedureFamily } from "./static/procedure-family.types";
|
|
6
|
-
import { ContraindicationDynamic } from "./admin-constants.types";
|
|
7
|
-
import { TreatmentBenefitDynamic } from "./admin-constants.types";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Reference to a documentation template with metadata
|
|
@@ -65,8 +65,8 @@ export interface Technology {
|
|
|
65
65
|
post: Requirement[];
|
|
66
66
|
};
|
|
67
67
|
blockingConditions: BlockingCondition[];
|
|
68
|
-
contraindications:
|
|
69
|
-
benefits:
|
|
68
|
+
contraindications: Contraindication[];
|
|
69
|
+
benefits: TreatmentBenefit[];
|
|
70
70
|
certificationRequirement: CertificationRequirement;
|
|
71
71
|
documentationTemplates?: TechnologyDocumentationTemplate[];
|
|
72
72
|
isActive: boolean;
|
|
@@ -1,53 +1,27 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { ProcedureFamily } from "../types/static/procedure-family.types";
|
|
3
3
|
import { BlockingCondition } from "../types/static/blocking-condition.types";
|
|
4
|
+
import { Contraindication } from "../types/static/contraindication.types";
|
|
5
|
+
import { TreatmentBenefit } from "../types/static/treatment-benefit.types";
|
|
4
6
|
import { TimeUnit, RequirementType } from "../types/requirement.types";
|
|
5
7
|
import {
|
|
6
8
|
CertificationLevel,
|
|
7
9
|
CertificationSpecialty,
|
|
8
10
|
} from "../types/static/certification.types";
|
|
9
|
-
|
|
11
|
+
import {
|
|
12
|
+
DocumentElementType,
|
|
13
|
+
HeadingLevel,
|
|
14
|
+
ListType,
|
|
15
|
+
} from "../types/documentation-templates.types";
|
|
10
16
|
import { documentTemplateSchema } from "../../validations/documentation-templates.schema";
|
|
11
17
|
|
|
12
|
-
/**
|
|
13
|
-
* Zod validation schema for a single dynamic contraindication.
|
|
14
|
-
* @see ContraindicationDynamic in admin-constants.types.ts
|
|
15
|
-
*/
|
|
16
|
-
export const contraindicationDynamicSchema = z.object({
|
|
17
|
-
id: z
|
|
18
|
-
.string()
|
|
19
|
-
.min(1, "Contraindication ID is required")
|
|
20
|
-
.regex(
|
|
21
|
-
/^[a-z0-9_]+$/,
|
|
22
|
-
"ID must be in snake_case (lowercase, numbers, and underscores only)"
|
|
23
|
-
),
|
|
24
|
-
name: z.string().min(1, "Contraindication name is required"),
|
|
25
|
-
description: z.string().optional(),
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Zod validation schema for a single dynamic treatment benefit.
|
|
30
|
-
* @see TreatmentBenefitDynamic in admin-constants.types.ts
|
|
31
|
-
*/
|
|
32
|
-
export const treatmentBenefitDynamicSchema = z.object({
|
|
33
|
-
id: z
|
|
34
|
-
.string()
|
|
35
|
-
.min(1, "Benefit ID is required")
|
|
36
|
-
.regex(
|
|
37
|
-
/^[a-z0-9_]+$/,
|
|
38
|
-
"ID must be in snake_case (lowercase, numbers, and underscores only)"
|
|
39
|
-
),
|
|
40
|
-
name: z.string().min(1, "Benefit name is required"),
|
|
41
|
-
description: z.string().optional(),
|
|
42
|
-
});
|
|
43
|
-
|
|
44
18
|
/**
|
|
45
19
|
* Base validation schemas for enums
|
|
46
20
|
*/
|
|
47
21
|
export const blockingConditionSchemaBackoffice =
|
|
48
22
|
z.nativeEnum(BlockingCondition);
|
|
49
|
-
export const contraindicationSchemaBackoffice =
|
|
50
|
-
export const treatmentBenefitSchemaBackoffice =
|
|
23
|
+
export const contraindicationSchemaBackoffice = z.nativeEnum(Contraindication);
|
|
24
|
+
export const treatmentBenefitSchemaBackoffice = z.nativeEnum(TreatmentBenefit);
|
|
51
25
|
export const procedureFamilySchemaBackoffice = z.nativeEnum(ProcedureFamily);
|
|
52
26
|
export const timeUnitSchemaBackoffice = z.nativeEnum(TimeUnit);
|
|
53
27
|
export const requirementTypeSchema = z.nativeEnum(RequirementType);
|
|
@@ -21,15 +21,18 @@ import { BaseService } from "../base.service";
|
|
|
21
21
|
import {
|
|
22
22
|
Appointment,
|
|
23
23
|
AppointmentStatus,
|
|
24
|
+
CreateAppointmentData,
|
|
24
25
|
UpdateAppointmentData,
|
|
25
26
|
SearchAppointmentsParams,
|
|
26
27
|
PaymentStatus,
|
|
27
28
|
AppointmentMediaItem,
|
|
28
29
|
PatientReviewInfo,
|
|
30
|
+
LinkedFormInfo,
|
|
29
31
|
type CreateAppointmentHttpData,
|
|
30
32
|
APPOINTMENTS_COLLECTION,
|
|
31
33
|
} from "../../types/appointment";
|
|
32
34
|
import {
|
|
35
|
+
createAppointmentSchema,
|
|
33
36
|
updateAppointmentSchema,
|
|
34
37
|
searchAppointmentsSchema,
|
|
35
38
|
rescheduleAppointmentSchema,
|
|
@@ -44,6 +47,8 @@ import { FilledDocumentService } from "../documentation-templates/filled-documen
|
|
|
44
47
|
|
|
45
48
|
// Import utility functions
|
|
46
49
|
import {
|
|
50
|
+
fetchAggregatedInfoUtil,
|
|
51
|
+
createAppointmentUtil,
|
|
47
52
|
updateAppointmentUtil,
|
|
48
53
|
getAppointmentByIdUtil,
|
|
49
54
|
searchAppointmentsUtil,
|
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
PractitionerProfileInfo,
|
|
34
34
|
} from "../../../types/profile";
|
|
35
35
|
import { BlockingCondition } from "../../../backoffice/types/static/blocking-condition.types";
|
|
36
|
+
import { Contraindication } from "../../../backoffice/types/static/contraindication.types";
|
|
36
37
|
import { Requirement } from "../../../backoffice/types/requirement.types";
|
|
37
38
|
import { PRACTITIONERS_COLLECTION } from "../../../types/practitioner";
|
|
38
39
|
import { CLINICS_COLLECTION } from "../../../types/clinic";
|
|
@@ -42,7 +43,6 @@ import {
|
|
|
42
43
|
Technology,
|
|
43
44
|
TECHNOLOGIES_COLLECTION,
|
|
44
45
|
} from "../../../backoffice/types/technology.types";
|
|
45
|
-
import type { ContraindicationDynamic } from "../../../backoffice";
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
48
|
* Fetches all the necessary information for an appointment by IDs.
|
|
@@ -66,7 +66,7 @@ export async function fetchAggregatedInfoUtil(
|
|
|
66
66
|
patientInfo: PatientProfileInfo;
|
|
67
67
|
procedureInfo: ProcedureSummaryInfo;
|
|
68
68
|
blockingConditions: BlockingCondition[];
|
|
69
|
-
contraindications:
|
|
69
|
+
contraindications: Contraindication[];
|
|
70
70
|
preProcedureRequirements: Requirement[];
|
|
71
71
|
postProcedureRequirements: Requirement[];
|
|
72
72
|
}> {
|
|
@@ -162,7 +162,7 @@ export async function fetchAggregatedInfoUtil(
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
let blockingConditions: BlockingCondition[] = [];
|
|
165
|
-
let contraindications:
|
|
165
|
+
let contraindications: Contraindication[] = [];
|
|
166
166
|
let preProcedureRequirements: Requirement[] = [];
|
|
167
167
|
let postProcedureRequirements: Requirement[] = [];
|
|
168
168
|
|
|
@@ -213,85 +213,85 @@ export async function fetchAggregatedInfoUtil(
|
|
|
213
213
|
* @param generateId Function to generate a unique ID
|
|
214
214
|
* @returns The created Appointment
|
|
215
215
|
*/
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
//
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
//
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
//
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
//
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
//
|
|
283
|
-
//
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
216
|
+
export async function createAppointmentUtil(
|
|
217
|
+
db: Firestore,
|
|
218
|
+
data: CreateAppointmentData,
|
|
219
|
+
aggregatedInfo: {
|
|
220
|
+
clinicInfo: ClinicInfo;
|
|
221
|
+
practitionerInfo: PractitionerProfileInfo;
|
|
222
|
+
patientInfo: PatientProfileInfo;
|
|
223
|
+
procedureInfo: ProcedureSummaryInfo;
|
|
224
|
+
blockingConditions: BlockingCondition[];
|
|
225
|
+
contraindications: Contraindication[];
|
|
226
|
+
preProcedureRequirements: Requirement[];
|
|
227
|
+
postProcedureRequirements: Requirement[];
|
|
228
|
+
},
|
|
229
|
+
generateId: () => string
|
|
230
|
+
): Promise<Appointment> {
|
|
231
|
+
try {
|
|
232
|
+
const appointmentId = generateId();
|
|
233
|
+
|
|
234
|
+
// Create appointment object
|
|
235
|
+
const appointment: Omit<Appointment, "createdAt" | "updatedAt"> & {
|
|
236
|
+
createdAt: any;
|
|
237
|
+
updatedAt: any;
|
|
238
|
+
} = {
|
|
239
|
+
id: appointmentId,
|
|
240
|
+
calendarEventId: data.calendarEventId,
|
|
241
|
+
clinicBranchId: data.clinicBranchId,
|
|
242
|
+
clinicInfo: aggregatedInfo.clinicInfo,
|
|
243
|
+
practitionerId: data.practitionerId,
|
|
244
|
+
practitionerInfo: aggregatedInfo.practitionerInfo,
|
|
245
|
+
patientId: data.patientId,
|
|
246
|
+
patientInfo: aggregatedInfo.patientInfo,
|
|
247
|
+
procedureId: data.procedureId,
|
|
248
|
+
procedureInfo: aggregatedInfo.procedureInfo,
|
|
249
|
+
status: data.initialStatus,
|
|
250
|
+
bookingTime: Timestamp.now(),
|
|
251
|
+
appointmentStartTime: data.appointmentStartTime,
|
|
252
|
+
appointmentEndTime: data.appointmentEndTime,
|
|
253
|
+
patientNotes: data.patientNotes || null,
|
|
254
|
+
cost: data.cost,
|
|
255
|
+
currency: data.currency,
|
|
256
|
+
paymentStatus: data.initialPaymentStatus || PaymentStatus.UNPAID,
|
|
257
|
+
blockingConditions: aggregatedInfo.blockingConditions,
|
|
258
|
+
contraindications: aggregatedInfo.contraindications,
|
|
259
|
+
preProcedureRequirements: aggregatedInfo.preProcedureRequirements,
|
|
260
|
+
postProcedureRequirements: aggregatedInfo.postProcedureRequirements,
|
|
261
|
+
completedPreRequirements: [],
|
|
262
|
+
completedPostRequirements: [],
|
|
263
|
+
createdAt: serverTimestamp(),
|
|
264
|
+
updatedAt: serverTimestamp(),
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
// Add additional fields for confirmation if appointment is already confirmed
|
|
268
|
+
if (data.initialStatus === AppointmentStatus.CONFIRMED) {
|
|
269
|
+
appointment.confirmationTime = Timestamp.now();
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Save to Firestore
|
|
273
|
+
await setDoc(doc(db, APPOINTMENTS_COLLECTION, appointmentId), appointment);
|
|
274
|
+
|
|
275
|
+
// Update the calendar event with the appointment ID
|
|
276
|
+
const calendarEventRef = doc(db, CALENDAR_COLLECTION, data.calendarEventId);
|
|
277
|
+
await updateDoc(calendarEventRef, {
|
|
278
|
+
appointmentId: appointmentId,
|
|
279
|
+
updatedAt: serverTimestamp(),
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
// Return the created appointment
|
|
283
|
+
// Convert serverTimestamp to regular Timestamp for immediate use
|
|
284
|
+
const now = Timestamp.now();
|
|
285
|
+
return {
|
|
286
|
+
...appointment,
|
|
287
|
+
createdAt: now,
|
|
288
|
+
updatedAt: now,
|
|
289
|
+
} as Appointment;
|
|
290
|
+
} catch (error) {
|
|
291
|
+
console.error("Error creating appointment:", error);
|
|
292
|
+
throw error;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
295
|
|
|
296
296
|
/**
|
|
297
297
|
* Updates an existing appointment in Firestore.
|
|
@@ -327,27 +327,23 @@ export async function updateAppointmentUtil(
|
|
|
327
327
|
const validPreReqIds = currentAppointment.preProcedureRequirements.map(
|
|
328
328
|
(req) => req.id
|
|
329
329
|
);
|
|
330
|
+
const invalidPreReqIds = data.completedPreRequirements.filter(
|
|
331
|
+
(id) => !validPreReqIds.includes(id)
|
|
332
|
+
);
|
|
330
333
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
(id) => !validPreReqIds.includes(id)
|
|
334
|
+
if (invalidPreReqIds.length > 0) {
|
|
335
|
+
throw new Error(
|
|
336
|
+
`Invalid pre-requirement IDs: ${invalidPreReqIds.join(", ")}`
|
|
335
337
|
);
|
|
336
|
-
|
|
337
|
-
if (invalidPreReqIds.length > 0) {
|
|
338
|
-
throw new Error(
|
|
339
|
-
`Invalid pre-requirement IDs: ${invalidPreReqIds.join(", ")}`
|
|
340
|
-
);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
// Update the completed pre-requirements
|
|
344
|
-
completedPreRequirements = [
|
|
345
|
-
...new Set([
|
|
346
|
-
...completedPreRequirements,
|
|
347
|
-
...data.completedPreRequirements,
|
|
348
|
-
]),
|
|
349
|
-
];
|
|
350
338
|
}
|
|
339
|
+
|
|
340
|
+
// Update the completed pre-requirements
|
|
341
|
+
completedPreRequirements = [
|
|
342
|
+
...new Set([
|
|
343
|
+
...completedPreRequirements,
|
|
344
|
+
...data.completedPreRequirements,
|
|
345
|
+
]),
|
|
346
|
+
];
|
|
351
347
|
}
|
|
352
348
|
|
|
353
349
|
if (data.completedPostRequirements) {
|
|
@@ -355,37 +351,30 @@ export async function updateAppointmentUtil(
|
|
|
355
351
|
const validPostReqIds = currentAppointment.postProcedureRequirements.map(
|
|
356
352
|
(req) => req.id
|
|
357
353
|
);
|
|
354
|
+
const invalidPostReqIds = data.completedPostRequirements.filter(
|
|
355
|
+
(id) => !validPostReqIds.includes(id)
|
|
356
|
+
);
|
|
358
357
|
|
|
359
|
-
if (
|
|
360
|
-
|
|
361
|
-
|
|
358
|
+
if (invalidPostReqIds.length > 0) {
|
|
359
|
+
throw new Error(
|
|
360
|
+
`Invalid post-requirement IDs: ${invalidPostReqIds.join(", ")}`
|
|
362
361
|
);
|
|
363
|
-
|
|
364
|
-
if (invalidPostReqIds.length > 0) {
|
|
365
|
-
throw new Error(
|
|
366
|
-
`Invalid post-requirement IDs: ${invalidPostReqIds.join(", ")}`
|
|
367
|
-
);
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
// Update the completed post-requirements
|
|
371
|
-
completedPostRequirements = [
|
|
372
|
-
...new Set([
|
|
373
|
-
...completedPostRequirements,
|
|
374
|
-
...data.completedPostRequirements,
|
|
375
|
-
]),
|
|
376
|
-
];
|
|
377
362
|
}
|
|
363
|
+
|
|
364
|
+
// Update the completed post-requirements
|
|
365
|
+
completedPostRequirements = [
|
|
366
|
+
...new Set([
|
|
367
|
+
...completedPostRequirements,
|
|
368
|
+
...data.completedPostRequirements,
|
|
369
|
+
]),
|
|
370
|
+
];
|
|
378
371
|
}
|
|
379
372
|
|
|
380
373
|
// Prepare update data
|
|
381
374
|
const updateData: any = {
|
|
382
375
|
...data,
|
|
383
|
-
completedPreRequirements
|
|
384
|
-
|
|
385
|
-
: data.completedPreRequirements,
|
|
386
|
-
completedPostRequirements: Array.isArray(data.completedPostRequirements)
|
|
387
|
-
? completedPostRequirements
|
|
388
|
-
: data.completedPostRequirements,
|
|
376
|
+
completedPreRequirements,
|
|
377
|
+
completedPostRequirements,
|
|
389
378
|
updatedAt: serverTimestamp(),
|
|
390
379
|
};
|
|
391
380
|
|
|
@@ -465,7 +454,7 @@ async function updateCalendarEventStatus(
|
|
|
465
454
|
case AppointmentStatus.CANCELED_CLINIC:
|
|
466
455
|
calendarStatus = "canceled";
|
|
467
456
|
break;
|
|
468
|
-
case AppointmentStatus.
|
|
457
|
+
case AppointmentStatus.RESCHEDULED:
|
|
469
458
|
calendarStatus = "rescheduled";
|
|
470
459
|
break;
|
|
471
460
|
case AppointmentStatus.COMPLETED:
|