@blackcode_sa/metaestetics-api 1.5.3 → 1.5.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/backoffice/index.d.mts +1306 -63
- package/dist/backoffice/index.d.ts +1306 -63
- package/dist/backoffice/index.js +35 -26
- package/dist/backoffice/index.mjs +35 -26
- package/dist/index.d.mts +17 -3
- package/dist/index.d.ts +17 -3
- package/dist/index.js +77 -0
- package/dist/index.mjs +77 -0
- package/package.json +1 -1
- package/src/backoffice/services/brand.service.ts +2 -4
- package/src/backoffice/services/category.service.ts +2 -7
- package/src/backoffice/services/product.service.ts +5 -7
- package/src/backoffice/services/requirement.service.ts +6 -7
- package/src/backoffice/services/subcategory.service.ts +11 -8
- package/src/backoffice/services/technology.service.ts +6 -11
- package/src/backoffice/types/brand.types.ts +5 -0
- package/src/backoffice/types/category.types.ts +5 -0
- package/src/backoffice/types/documentation-templates.types.ts +4 -0
- package/src/backoffice/types/product.types.ts +5 -0
- package/src/backoffice/types/requirement.types.ts +5 -0
- package/src/backoffice/types/subcategory.types.ts +5 -0
- package/src/backoffice/types/technology.types.ts +10 -0
- package/src/backoffice/validations/schemas.ts +2 -0
- package/src/errors/auth.errors.ts +7 -0
- package/src/services/auth.service.ts +94 -0
- package/src/services/documentation-templates/documentation-template.service.ts +4 -1
- package/src/services/procedure/procedure.service.ts +238 -0
- package/src/types/documentation-templates/index.ts +5 -0
- package/src/types/procedure/index.ts +104 -0
- package/src/validations/procedure.schema.ts +58 -0
|
@@ -8,14 +8,13 @@ import {
|
|
|
8
8
|
updateDoc,
|
|
9
9
|
where,
|
|
10
10
|
} from "firebase/firestore";
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
Requirement,
|
|
13
|
+
RequirementType,
|
|
14
|
+
REQUIREMENTS_COLLECTION,
|
|
15
|
+
} from "../types/requirement.types";
|
|
12
16
|
import { BaseService } from "../../services/base.service";
|
|
13
17
|
|
|
14
|
-
/**
|
|
15
|
-
* Kolekcija u Firestore bazi gde se čuvaju globalni zahtevi
|
|
16
|
-
*/
|
|
17
|
-
const COLLECTION = "backoffice_requirements";
|
|
18
|
-
|
|
19
18
|
/**
|
|
20
19
|
* Servis za upravljanje globalnim zahtevima.
|
|
21
20
|
* Zahtevi se mogu kreirati globalno i zatim povezati sa različitim tehnologijama.
|
|
@@ -42,7 +41,7 @@ export class RequirementService extends BaseService {
|
|
|
42
41
|
* Referenca na Firestore kolekciju zahteva
|
|
43
42
|
*/
|
|
44
43
|
private get requirementsRef() {
|
|
45
|
-
return collection(this.db,
|
|
44
|
+
return collection(this.db, REQUIREMENTS_COLLECTION);
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
/**
|
|
@@ -8,14 +8,12 @@ import {
|
|
|
8
8
|
updateDoc,
|
|
9
9
|
where,
|
|
10
10
|
} from "firebase/firestore";
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
Subcategory,
|
|
13
|
+
SUBCATEGORIES_COLLECTION,
|
|
14
|
+
} from "../types/subcategory.types";
|
|
12
15
|
import { BaseService } from "../../services/base.service";
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Kolekcije u Firestore bazi
|
|
16
|
-
*/
|
|
17
|
-
const COLLECTION = "backoffice_categories";
|
|
18
|
-
const SUB_COLLECTION = "subcategories";
|
|
16
|
+
import { CATEGORIES_COLLECTION } from "../types/category.types";
|
|
19
17
|
|
|
20
18
|
/**
|
|
21
19
|
* Servis za upravljanje podkategorijama procedura.
|
|
@@ -36,7 +34,12 @@ export class SubcategoryService extends BaseService {
|
|
|
36
34
|
* @param categoryId - ID roditeljske kategorije
|
|
37
35
|
*/
|
|
38
36
|
private getSubcategoriesRef(categoryId: string) {
|
|
39
|
-
return collection(
|
|
37
|
+
return collection(
|
|
38
|
+
this.db,
|
|
39
|
+
CATEGORIES_COLLECTION,
|
|
40
|
+
categoryId,
|
|
41
|
+
SUBCATEGORIES_COLLECTION
|
|
42
|
+
);
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
/**
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
arrayRemove,
|
|
12
12
|
Firestore,
|
|
13
13
|
} from "firebase/firestore";
|
|
14
|
-
import { Technology } from "../types/technology.types";
|
|
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
17
|
import { Contraindication } from "../types/static/contraindication.types";
|
|
@@ -22,13 +22,8 @@ import {
|
|
|
22
22
|
CertificationRequirement,
|
|
23
23
|
} from "../types/static/certification.types";
|
|
24
24
|
import { BaseService } from "../../services/base.service";
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
* Kolekcije u Firestore bazi
|
|
28
|
-
*/
|
|
29
|
-
const COLLECTION = "backoffice_categories";
|
|
30
|
-
const SUB_COLLECTION_SUBCATEGORIES = "subcategories";
|
|
31
|
-
const SUB_COLLECTION_TECHNOLOGIES = "technologies";
|
|
25
|
+
import { SUBCATEGORIES_COLLECTION } from "../types/subcategory.types";
|
|
26
|
+
import { CATEGORIES_COLLECTION } from "../types/category.types";
|
|
32
27
|
|
|
33
28
|
/**
|
|
34
29
|
* Default vrednosti za sertifikaciju
|
|
@@ -68,11 +63,11 @@ export class TechnologyService extends BaseService {
|
|
|
68
63
|
private getTechnologiesRef(categoryId: string, subcategoryId: string) {
|
|
69
64
|
return collection(
|
|
70
65
|
this.db,
|
|
71
|
-
|
|
66
|
+
CATEGORIES_COLLECTION,
|
|
72
67
|
categoryId,
|
|
73
|
-
|
|
68
|
+
SUBCATEGORIES_COLLECTION,
|
|
74
69
|
subcategoryId,
|
|
75
|
-
|
|
70
|
+
TECHNOLOGIES_COLLECTION
|
|
76
71
|
);
|
|
77
72
|
}
|
|
78
73
|
|
|
@@ -7,6 +7,8 @@ import {
|
|
|
7
7
|
HeadingLevel,
|
|
8
8
|
ListType,
|
|
9
9
|
DynamicVariable,
|
|
10
|
+
DOCUMENTATION_TEMPLATES_COLLECTION,
|
|
11
|
+
FILLED_DOCUMENTS_COLLECTION,
|
|
10
12
|
} from "../../types/documentation-templates";
|
|
11
13
|
|
|
12
14
|
/**
|
|
@@ -22,3 +24,5 @@ export {
|
|
|
22
24
|
ListType,
|
|
23
25
|
DynamicVariable,
|
|
24
26
|
};
|
|
27
|
+
|
|
28
|
+
export { DOCUMENTATION_TEMPLATES_COLLECTION, FILLED_DOCUMENTS_COLLECTION };
|
|
@@ -3,6 +3,7 @@ import { BlockingCondition } from "./static/blocking-condition.types";
|
|
|
3
3
|
import { Contraindication } from "./static/contraindication.types";
|
|
4
4
|
import { TreatmentBenefit } from "./static/treatment-benefit.types";
|
|
5
5
|
import { CertificationRequirement } from "./static/certification.types";
|
|
6
|
+
import { DocumentTemplate } from "../../types/documentation-templates";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Zahtevi koji su povezani sa tehnologijom
|
|
@@ -29,6 +30,7 @@ export interface TechnologyRequirements {
|
|
|
29
30
|
* @property contraindications - List of conditions requiring special attention
|
|
30
31
|
* @property benefits - List of expected benefits from the procedure
|
|
31
32
|
* @property certificationRequirement - Required certification level and specialties
|
|
33
|
+
* @property documentationTemplates - List of documentation templates required for this technology
|
|
32
34
|
* @property isActive - Whether the technology is active in the system
|
|
33
35
|
* @property createdAt - Creation date
|
|
34
36
|
* @property updatedAt - Last update date
|
|
@@ -66,6 +68,9 @@ export interface Technology {
|
|
|
66
68
|
/** Potrebna sertifikacija za korišćenje tehnologije */
|
|
67
69
|
certificationRequirement: CertificationRequirement;
|
|
68
70
|
|
|
71
|
+
/** Dokumentacioni šabloni potrebni za ovu tehnologiju */
|
|
72
|
+
documentationTemplates?: DocumentTemplate[];
|
|
73
|
+
|
|
69
74
|
/** Da li je tehnologija trenutno aktivna */
|
|
70
75
|
isActive: boolean;
|
|
71
76
|
|
|
@@ -75,3 +80,8 @@ export interface Technology {
|
|
|
75
80
|
/** Datum poslednjeg ažuriranja */
|
|
76
81
|
updatedAt: Date;
|
|
77
82
|
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Kolekcija u Firestore bazi gde se čuvaju tehnologije
|
|
86
|
+
*/
|
|
87
|
+
export const TECHNOLOGIES_COLLECTION = "technologies";
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
HeadingLevel,
|
|
14
14
|
ListType,
|
|
15
15
|
} from "../types/documentation-templates.types";
|
|
16
|
+
import { documentTemplateSchema } from "../../validations/documentation-templates.schema";
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Base validation schemas for enums
|
|
@@ -87,6 +88,7 @@ export const technologySchema = z.object({
|
|
|
87
88
|
}),
|
|
88
89
|
blockingConditions: z.array(blockingConditionSchema),
|
|
89
90
|
contraindications: z.array(contraindicationSchema),
|
|
91
|
+
documentationTemplates: z.array(documentTemplateSchema),
|
|
90
92
|
benefits: z.array(treatmentBenefitSchema),
|
|
91
93
|
certificationRequirement: certificationRequirementSchema,
|
|
92
94
|
isActive: z.boolean().default(true),
|
|
@@ -134,6 +134,13 @@ export const AUTH_ERRORS = {
|
|
|
134
134
|
401
|
|
135
135
|
),
|
|
136
136
|
|
|
137
|
+
// Resource not found
|
|
138
|
+
NOT_FOUND: new AuthError(
|
|
139
|
+
"The requested resource was not found",
|
|
140
|
+
"AUTH/NOT_FOUND",
|
|
141
|
+
404
|
|
142
|
+
),
|
|
143
|
+
|
|
137
144
|
// Detailed password validation errors
|
|
138
145
|
PASSWORD_LENGTH_ERROR: new AuthError(
|
|
139
146
|
"Password must be at least 8 characters long",
|
|
@@ -471,6 +471,100 @@ export class AuthService extends BaseService {
|
|
|
471
471
|
return this.userService.getOrCreateUser(firebaseUser);
|
|
472
472
|
}
|
|
473
473
|
|
|
474
|
+
/**
|
|
475
|
+
* Prijavljuje korisnika sa email-om i lozinkom samo za clinic_admin role
|
|
476
|
+
* @param email - Email korisnika
|
|
477
|
+
* @param password - Lozinka korisnika
|
|
478
|
+
* @returns Objekat koji sadrži korisnika, admin profil i grupu klinika
|
|
479
|
+
* @throws {AUTH_ERRORS.INVALID_ROLE} Ako korisnik nema clinic_admin rolu
|
|
480
|
+
* @throws {AUTH_ERRORS.NOT_FOUND} Ako admin profil nije pronađen
|
|
481
|
+
*/
|
|
482
|
+
async signInClinicAdmin(
|
|
483
|
+
email: string,
|
|
484
|
+
password: string
|
|
485
|
+
): Promise<{
|
|
486
|
+
user: User;
|
|
487
|
+
clinicAdmin: ClinicAdmin;
|
|
488
|
+
clinicGroup: ClinicGroup;
|
|
489
|
+
}> {
|
|
490
|
+
try {
|
|
491
|
+
// Initialize required services
|
|
492
|
+
const clinicAdminService = new ClinicAdminService(
|
|
493
|
+
this.db,
|
|
494
|
+
this.auth,
|
|
495
|
+
this.app
|
|
496
|
+
);
|
|
497
|
+
const clinicGroupService = new ClinicGroupService(
|
|
498
|
+
this.db,
|
|
499
|
+
this.auth,
|
|
500
|
+
this.app,
|
|
501
|
+
clinicAdminService
|
|
502
|
+
);
|
|
503
|
+
const clinicService = new ClinicService(
|
|
504
|
+
this.db,
|
|
505
|
+
this.auth,
|
|
506
|
+
this.app,
|
|
507
|
+
clinicGroupService,
|
|
508
|
+
clinicAdminService
|
|
509
|
+
);
|
|
510
|
+
|
|
511
|
+
// Set services to resolve circular dependencies
|
|
512
|
+
clinicAdminService.setServices(clinicGroupService, clinicService);
|
|
513
|
+
|
|
514
|
+
// Sign in with email/password
|
|
515
|
+
const { user: firebaseUser } = await signInWithEmailAndPassword(
|
|
516
|
+
this.auth,
|
|
517
|
+
email,
|
|
518
|
+
password
|
|
519
|
+
);
|
|
520
|
+
|
|
521
|
+
// Get or create user
|
|
522
|
+
const user = await this.userService.getOrCreateUser(firebaseUser);
|
|
523
|
+
|
|
524
|
+
// Check if user has clinic_admin role
|
|
525
|
+
if (!user.roles?.includes(UserRole.CLINIC_ADMIN)) {
|
|
526
|
+
console.error("[AUTH] User is not a clinic admin:", user.uid);
|
|
527
|
+
throw AUTH_ERRORS.INVALID_ROLE;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// Check and get admin profile
|
|
531
|
+
if (!user.adminProfile) {
|
|
532
|
+
console.error("[AUTH] User has no admin profile:", user.uid);
|
|
533
|
+
throw AUTH_ERRORS.NOT_FOUND;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// Get clinic admin profile
|
|
537
|
+
const adminProfile = await clinicAdminService.getClinicAdmin(
|
|
538
|
+
user.adminProfile
|
|
539
|
+
);
|
|
540
|
+
if (!adminProfile) {
|
|
541
|
+
console.error("[AUTH] Admin profile not found:", user.adminProfile);
|
|
542
|
+
throw AUTH_ERRORS.NOT_FOUND;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// Get clinic group
|
|
546
|
+
const clinicGroup = await clinicGroupService.getClinicGroup(
|
|
547
|
+
adminProfile.clinicGroupId
|
|
548
|
+
);
|
|
549
|
+
if (!clinicGroup) {
|
|
550
|
+
console.error(
|
|
551
|
+
"[AUTH] Clinic group not found:",
|
|
552
|
+
adminProfile.clinicGroupId
|
|
553
|
+
);
|
|
554
|
+
throw AUTH_ERRORS.NOT_FOUND;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
return {
|
|
558
|
+
user,
|
|
559
|
+
clinicAdmin: adminProfile,
|
|
560
|
+
clinicGroup,
|
|
561
|
+
};
|
|
562
|
+
} catch (error) {
|
|
563
|
+
console.error("[AUTH] Error in signInClinicAdmin:", error);
|
|
564
|
+
throw error;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
474
568
|
/**
|
|
475
569
|
* Prijavljuje korisnika sa Facebook-om
|
|
476
570
|
*/
|
|
@@ -21,9 +21,12 @@ import {
|
|
|
21
21
|
CreateDocumentTemplateData,
|
|
22
22
|
DocumentElement,
|
|
23
23
|
DocumentTemplate,
|
|
24
|
-
DOCUMENTATION_TEMPLATES_COLLECTION,
|
|
25
24
|
UpdateDocumentTemplateData,
|
|
26
25
|
} from "../../types";
|
|
26
|
+
import {
|
|
27
|
+
FILLED_DOCUMENTS_COLLECTION,
|
|
28
|
+
DOCUMENTATION_TEMPLATES_COLLECTION,
|
|
29
|
+
} from "../../types";
|
|
27
30
|
import {
|
|
28
31
|
createDocumentTemplateSchema,
|
|
29
32
|
updateDocumentTemplateSchema,
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import {
|
|
2
|
+
collection,
|
|
3
|
+
doc,
|
|
4
|
+
getDoc,
|
|
5
|
+
getDocs,
|
|
6
|
+
query,
|
|
7
|
+
where,
|
|
8
|
+
updateDoc,
|
|
9
|
+
setDoc,
|
|
10
|
+
deleteDoc,
|
|
11
|
+
Timestamp,
|
|
12
|
+
serverTimestamp,
|
|
13
|
+
DocumentData,
|
|
14
|
+
} from "firebase/firestore";
|
|
15
|
+
import { BaseService } from "../base.service";
|
|
16
|
+
import {
|
|
17
|
+
Procedure,
|
|
18
|
+
CreateProcedureData,
|
|
19
|
+
UpdateProcedureData,
|
|
20
|
+
PROCEDURES_COLLECTION,
|
|
21
|
+
} from "../../types/procedure";
|
|
22
|
+
import {
|
|
23
|
+
createProcedureSchema,
|
|
24
|
+
updateProcedureSchema,
|
|
25
|
+
} from "../../validations/procedure.schema";
|
|
26
|
+
import { z } from "zod";
|
|
27
|
+
import { Auth } from "firebase/auth";
|
|
28
|
+
import { Firestore } from "firebase/firestore";
|
|
29
|
+
import { FirebaseApp } from "firebase/app";
|
|
30
|
+
import {
|
|
31
|
+
Category,
|
|
32
|
+
CATEGORIES_COLLECTION,
|
|
33
|
+
} from "../../backoffice/types/category.types";
|
|
34
|
+
import {
|
|
35
|
+
Subcategory,
|
|
36
|
+
SUBCATEGORIES_COLLECTION,
|
|
37
|
+
} from "../../backoffice/types/subcategory.types";
|
|
38
|
+
import {
|
|
39
|
+
Technology,
|
|
40
|
+
TECHNOLOGIES_COLLECTION,
|
|
41
|
+
} from "../../backoffice/types/technology.types";
|
|
42
|
+
import {
|
|
43
|
+
Product,
|
|
44
|
+
PRODUCTS_COLLECTION,
|
|
45
|
+
} from "../../backoffice/types/product.types";
|
|
46
|
+
|
|
47
|
+
export class ProcedureService extends BaseService {
|
|
48
|
+
constructor(db: Firestore, auth: Auth, app: FirebaseApp) {
|
|
49
|
+
super(db, auth, app);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Creates a new procedure
|
|
54
|
+
* @param data - The data for creating a new procedure
|
|
55
|
+
* @returns The created procedure
|
|
56
|
+
*/
|
|
57
|
+
async createProcedure(data: CreateProcedureData): Promise<Procedure> {
|
|
58
|
+
// Validate input data
|
|
59
|
+
const validatedData = createProcedureSchema.parse(data);
|
|
60
|
+
|
|
61
|
+
// Get references to related entities
|
|
62
|
+
const [category, subcategory, technology, product] = await Promise.all([
|
|
63
|
+
this.getCategory(validatedData.categoryId),
|
|
64
|
+
this.getSubcategory(validatedData.subcategoryId),
|
|
65
|
+
this.getTechnology(validatedData.technologyId),
|
|
66
|
+
this.getProduct(validatedData.productId),
|
|
67
|
+
]);
|
|
68
|
+
|
|
69
|
+
if (!category || !subcategory || !technology || !product) {
|
|
70
|
+
throw new Error("One or more required entities not found");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Create the procedure object
|
|
74
|
+
const procedure: Omit<Procedure, "id"> = {
|
|
75
|
+
...validatedData,
|
|
76
|
+
category,
|
|
77
|
+
subcategory,
|
|
78
|
+
technology,
|
|
79
|
+
product,
|
|
80
|
+
blockingConditions: technology.blockingConditions,
|
|
81
|
+
treatmentBenefits: technology.benefits,
|
|
82
|
+
preRequirements: technology.requirements.pre,
|
|
83
|
+
postRequirements: technology.requirements.post,
|
|
84
|
+
certificationRequirement: technology.certificationRequirement,
|
|
85
|
+
documentationTemplates: technology.documentationTemplates || [],
|
|
86
|
+
isActive: true,
|
|
87
|
+
createdAt: new Date(),
|
|
88
|
+
updatedAt: new Date(),
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// Generate ID and create document
|
|
92
|
+
const id = this.generateId();
|
|
93
|
+
const docRef = doc(this.db, PROCEDURES_COLLECTION, id);
|
|
94
|
+
await setDoc(docRef, {
|
|
95
|
+
...procedure,
|
|
96
|
+
id,
|
|
97
|
+
createdAt: serverTimestamp(),
|
|
98
|
+
updatedAt: serverTimestamp(),
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
return { ...procedure, id } as Procedure;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Gets a procedure by ID
|
|
106
|
+
* @param id - The ID of the procedure to get
|
|
107
|
+
* @returns The procedure if found, null otherwise
|
|
108
|
+
*/
|
|
109
|
+
async getProcedure(id: string): Promise<Procedure | null> {
|
|
110
|
+
const docRef = doc(this.db, PROCEDURES_COLLECTION, id);
|
|
111
|
+
const docSnap = await getDoc(docRef);
|
|
112
|
+
|
|
113
|
+
if (!docSnap.exists()) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return docSnap.data() as Procedure;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Gets all procedures for a clinic branch
|
|
122
|
+
* @param clinicBranchId - The ID of the clinic branch
|
|
123
|
+
* @returns List of procedures
|
|
124
|
+
*/
|
|
125
|
+
async getProceduresByClinicBranch(
|
|
126
|
+
clinicBranchId: string
|
|
127
|
+
): Promise<Procedure[]> {
|
|
128
|
+
const q = query(
|
|
129
|
+
collection(this.db, PROCEDURES_COLLECTION),
|
|
130
|
+
where("clinicBranchId", "==", clinicBranchId),
|
|
131
|
+
where("isActive", "==", true)
|
|
132
|
+
);
|
|
133
|
+
const snapshot = await getDocs(q);
|
|
134
|
+
return snapshot.docs.map((doc) => doc.data() as Procedure);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Gets all procedures for a practitioner
|
|
139
|
+
* @param practitionerId - The ID of the practitioner
|
|
140
|
+
* @returns List of procedures
|
|
141
|
+
*/
|
|
142
|
+
async getProceduresByPractitioner(
|
|
143
|
+
practitionerId: string
|
|
144
|
+
): Promise<Procedure[]> {
|
|
145
|
+
const q = query(
|
|
146
|
+
collection(this.db, PROCEDURES_COLLECTION),
|
|
147
|
+
where("practitionerId", "==", practitionerId),
|
|
148
|
+
where("isActive", "==", true)
|
|
149
|
+
);
|
|
150
|
+
const snapshot = await getDocs(q);
|
|
151
|
+
return snapshot.docs.map((doc) => doc.data() as Procedure);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Updates a procedure
|
|
156
|
+
* @param id - The ID of the procedure to update
|
|
157
|
+
* @param data - The data to update
|
|
158
|
+
* @returns The updated procedure
|
|
159
|
+
*/
|
|
160
|
+
async updateProcedure(
|
|
161
|
+
id: string,
|
|
162
|
+
data: UpdateProcedureData
|
|
163
|
+
): Promise<Procedure> {
|
|
164
|
+
// Validate input data
|
|
165
|
+
const validatedData = updateProcedureSchema.parse(data);
|
|
166
|
+
|
|
167
|
+
// Get the existing procedure
|
|
168
|
+
const existingProcedure = await this.getProcedure(id);
|
|
169
|
+
if (!existingProcedure) {
|
|
170
|
+
throw new Error(`Procedure with ID ${id} not found`);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Update the procedure
|
|
174
|
+
const docRef = doc(this.db, PROCEDURES_COLLECTION, id);
|
|
175
|
+
await updateDoc(docRef, {
|
|
176
|
+
...validatedData,
|
|
177
|
+
updatedAt: serverTimestamp(),
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
...existingProcedure,
|
|
182
|
+
...validatedData,
|
|
183
|
+
updatedAt: new Date(),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Deactivates a procedure
|
|
189
|
+
* @param id - The ID of the procedure to deactivate
|
|
190
|
+
*/
|
|
191
|
+
async deactivateProcedure(id: string): Promise<void> {
|
|
192
|
+
const docRef = doc(this.db, PROCEDURES_COLLECTION, id);
|
|
193
|
+
await updateDoc(docRef, {
|
|
194
|
+
isActive: false,
|
|
195
|
+
updatedAt: serverTimestamp(),
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Gets a category by ID
|
|
201
|
+
* @private
|
|
202
|
+
*/
|
|
203
|
+
private async getCategory(id: string): Promise<Category | null> {
|
|
204
|
+
const docRef = doc(this.db, CATEGORIES_COLLECTION, id);
|
|
205
|
+
const docSnap = await getDoc(docRef);
|
|
206
|
+
return docSnap.exists() ? (docSnap.data() as Category) : null;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Gets a subcategory by ID
|
|
211
|
+
* @private
|
|
212
|
+
*/
|
|
213
|
+
private async getSubcategory(id: string): Promise<Subcategory | null> {
|
|
214
|
+
const docRef = doc(this.db, SUBCATEGORIES_COLLECTION, id);
|
|
215
|
+
const docSnap = await getDoc(docRef);
|
|
216
|
+
return docSnap.exists() ? (docSnap.data() as Subcategory) : null;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Gets a technology by ID
|
|
221
|
+
* @private
|
|
222
|
+
*/
|
|
223
|
+
private async getTechnology(id: string): Promise<Technology | null> {
|
|
224
|
+
const docRef = doc(this.db, TECHNOLOGIES_COLLECTION, id);
|
|
225
|
+
const docSnap = await getDoc(docRef);
|
|
226
|
+
return docSnap.exists() ? (docSnap.data() as Technology) : null;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Gets a product by ID
|
|
231
|
+
* @private
|
|
232
|
+
*/
|
|
233
|
+
private async getProduct(id: string): Promise<Product | null> {
|
|
234
|
+
const docRef = doc(this.db, PRODUCTS_COLLECTION, id);
|
|
235
|
+
const docSnap = await getDoc(docRef);
|
|
236
|
+
return docSnap.exists() ? (docSnap.data() as Product) : null;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
* Types for the Medical Documentation Templating System
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Kolekcija u Firestore bazi gde se čuvaju dokumentacijske šablone
|
|
7
|
+
*/
|
|
8
|
+
export const DOCUMENTATION_TEMPLATES_COLLECTION = "documentation-templates";
|
|
9
|
+
export const FILLED_DOCUMENTS_COLLECTION = "filled-documents";
|
|
5
10
|
/**
|
|
6
11
|
* Enum for element types in documentation templates
|
|
7
12
|
*/
|