@blackcode_sa/metaestetics-api 1.8.0 → 1.8.1
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 +956 -848
- package/dist/admin/index.d.ts +956 -848
- package/dist/admin/index.js +7215 -6757
- package/dist/admin/index.mjs +7215 -6754
- package/dist/backoffice/index.d.mts +1418 -1418
- package/dist/backoffice/index.d.ts +1418 -1418
- package/dist/backoffice/index.js +1464 -1454
- package/dist/backoffice/index.mjs +1509 -1499
- package/dist/index.d.mts +5565 -5565
- package/dist/index.d.ts +5565 -5565
- package/dist/index.js +9229 -9225
- package/dist/index.mjs +9324 -9320
- package/package.json +1 -1
- package/src/admin/aggregation/appointment/index.ts +1 -0
- package/src/admin/aggregation/clinic/index.ts +1 -0
- package/src/admin/aggregation/forms/index.ts +1 -0
- package/src/admin/aggregation/index.ts +8 -0
- package/src/admin/aggregation/patient/index.ts +1 -0
- package/src/admin/aggregation/practitioner/index.ts +1 -0
- package/src/admin/aggregation/practitioner-invite/index.ts +1 -0
- package/src/admin/aggregation/procedure/index.ts +1 -0
- package/src/admin/aggregation/reviews/index.ts +1 -0
- package/src/admin/booking/index.ts +1 -1
- package/src/admin/calendar/index.ts +1 -0
- package/src/admin/documentation-templates/index.ts +1 -0
- package/src/admin/free-consultation/index.ts +1 -0
- package/src/admin/index.ts +18 -120
- package/src/admin/mailing/appointment/index.ts +1 -0
- package/src/admin/mailing/index.ts +1 -2
- package/src/admin/mailing/practitionerInvite/index.ts +1 -0
- package/src/admin/notifications/index.ts +1 -0
- package/src/admin/requirements/index.ts +1 -0
- package/src/admin/users/index.ts +1 -0
- package/src/admin/users/user-profile.admin.ts +1 -0
- package/src/backoffice/constants/index.ts +1 -0
- package/src/backoffice/errors/index.ts +1 -0
- package/src/backoffice/index.ts +5 -14
- package/src/backoffice/services/index.ts +7 -0
- package/src/backoffice/validations/index.ts +1 -0
- package/src/services/index.ts +12 -14
|
@@ -1,323 +1,293 @@
|
|
|
1
|
+
// src/backoffice/services/brand.service.ts
|
|
2
|
+
import {
|
|
3
|
+
addDoc,
|
|
4
|
+
collection,
|
|
5
|
+
doc,
|
|
6
|
+
getDoc,
|
|
7
|
+
getDocs,
|
|
8
|
+
query,
|
|
9
|
+
updateDoc,
|
|
10
|
+
where
|
|
11
|
+
} from "firebase/firestore";
|
|
12
|
+
|
|
1
13
|
// src/backoffice/types/brand.types.ts
|
|
2
14
|
var BRANDS_COLLECTION = "brands";
|
|
3
15
|
|
|
4
|
-
// src/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
TimeUnit2["HOURS"] = "hours";
|
|
13
|
-
TimeUnit2["DAYS"] = "days";
|
|
14
|
-
return TimeUnit2;
|
|
15
|
-
})(TimeUnit || {});
|
|
16
|
-
var RequirementType = /* @__PURE__ */ ((RequirementType3) => {
|
|
17
|
-
RequirementType3["PRE"] = "pre";
|
|
18
|
-
RequirementType3["POST"] = "post";
|
|
19
|
-
return RequirementType3;
|
|
20
|
-
})(RequirementType || {});
|
|
21
|
-
var REQUIREMENTS_COLLECTION = "backoffice_requirements";
|
|
22
|
-
|
|
23
|
-
// src/backoffice/types/subcategory.types.ts
|
|
24
|
-
var SUBCATEGORIES_COLLECTION = "subcategories";
|
|
25
|
-
|
|
26
|
-
// src/backoffice/types/technology.types.ts
|
|
27
|
-
var TECHNOLOGIES_COLLECTION = "technologies";
|
|
28
|
-
|
|
29
|
-
// src/backoffice/types/static/blocking-condition.types.ts
|
|
30
|
-
var BlockingCondition = /* @__PURE__ */ ((BlockingCondition2) => {
|
|
31
|
-
BlockingCondition2["PREGNANCY"] = "pregnancy";
|
|
32
|
-
BlockingCondition2["BREASTFEEDING"] = "breastfeeding";
|
|
33
|
-
BlockingCondition2["ACTIVE_INFECTION"] = "active_infection";
|
|
34
|
-
BlockingCondition2["SKIN_CONDITION"] = "skin_condition";
|
|
35
|
-
BlockingCondition2["AUTOIMMUNE_DISEASE"] = "autoimmune_disease";
|
|
36
|
-
BlockingCondition2["BLOOD_THINNERS"] = "blood_thinners";
|
|
37
|
-
BlockingCondition2["RECENT_SURGERY"] = "recent_surgery";
|
|
38
|
-
BlockingCondition2["DIABETES"] = "diabetes";
|
|
39
|
-
BlockingCondition2["HEART_CONDITION"] = "heart_condition";
|
|
40
|
-
BlockingCondition2["HIGH_BLOOD_PRESSURE"] = "high_blood_pressure";
|
|
41
|
-
BlockingCondition2["KELOID_SCARRING"] = "keloid_scarring";
|
|
42
|
-
BlockingCondition2["METAL_IMPLANTS"] = "metal_implants";
|
|
43
|
-
BlockingCondition2["PACEMAKER"] = "pacemaker";
|
|
44
|
-
BlockingCondition2["CANCER"] = "cancer";
|
|
45
|
-
BlockingCondition2["EPILEPSY"] = "epilepsy";
|
|
46
|
-
return BlockingCondition2;
|
|
47
|
-
})(BlockingCondition || {});
|
|
48
|
-
|
|
49
|
-
// src/backoffice/types/static/certification.types.ts
|
|
50
|
-
var CertificationLevel = /* @__PURE__ */ ((CertificationLevel2) => {
|
|
51
|
-
CertificationLevel2["AESTHETICIAN"] = "aesthetician";
|
|
52
|
-
CertificationLevel2["NURSE_ASSISTANT"] = "nurse_assistant";
|
|
53
|
-
CertificationLevel2["NURSE"] = "nurse";
|
|
54
|
-
CertificationLevel2["NURSE_PRACTITIONER"] = "nurse_practitioner";
|
|
55
|
-
CertificationLevel2["PHYSICIAN_ASSISTANT"] = "physician_assistant";
|
|
56
|
-
CertificationLevel2["DOCTOR"] = "doctor";
|
|
57
|
-
CertificationLevel2["SPECIALIST"] = "specialist";
|
|
58
|
-
CertificationLevel2["PLASTIC_SURGEON"] = "plastic_surgeon";
|
|
59
|
-
return CertificationLevel2;
|
|
60
|
-
})(CertificationLevel || {});
|
|
61
|
-
var CertificationSpecialty = /* @__PURE__ */ ((CertificationSpecialty3) => {
|
|
62
|
-
CertificationSpecialty3["LASER"] = "laser";
|
|
63
|
-
CertificationSpecialty3["INJECTABLES"] = "injectables";
|
|
64
|
-
CertificationSpecialty3["CHEMICAL_PEELS"] = "chemical_peels";
|
|
65
|
-
CertificationSpecialty3["MICRODERMABRASION"] = "microdermabrasion";
|
|
66
|
-
CertificationSpecialty3["BODY_CONTOURING"] = "body_contouring";
|
|
67
|
-
CertificationSpecialty3["SKIN_CARE"] = "skin_care";
|
|
68
|
-
CertificationSpecialty3["WOUND_CARE"] = "wound_care";
|
|
69
|
-
CertificationSpecialty3["ANESTHESIA"] = "anesthesia";
|
|
70
|
-
return CertificationSpecialty3;
|
|
71
|
-
})(CertificationSpecialty || {});
|
|
72
|
-
|
|
73
|
-
// src/backoffice/types/static/contraindication.types.ts
|
|
74
|
-
var Contraindication = /* @__PURE__ */ ((Contraindication2) => {
|
|
75
|
-
Contraindication2["SENSITIVE_SKIN"] = "sensitive_skin";
|
|
76
|
-
Contraindication2["RECENT_TANNING"] = "recent_tanning";
|
|
77
|
-
Contraindication2["RECENT_BOTOX"] = "recent_botox";
|
|
78
|
-
Contraindication2["RECENT_FILLERS"] = "recent_fillers";
|
|
79
|
-
Contraindication2["SKIN_ALLERGIES"] = "skin_allergies";
|
|
80
|
-
Contraindication2["MEDICATIONS"] = "medications";
|
|
81
|
-
Contraindication2["RECENT_CHEMICAL_PEEL"] = "recent_chemical_peel";
|
|
82
|
-
Contraindication2["RECENT_LASER"] = "recent_laser";
|
|
83
|
-
Contraindication2["SKIN_INFLAMMATION"] = "skin_inflammation";
|
|
84
|
-
Contraindication2["OPEN_WOUNDS"] = "open_wounds";
|
|
85
|
-
Contraindication2["HERPES_SIMPLEX"] = "herpes_simplex";
|
|
86
|
-
Contraindication2["COLD_SORES"] = "cold_sores";
|
|
87
|
-
return Contraindication2;
|
|
88
|
-
})(Contraindication || {});
|
|
89
|
-
|
|
90
|
-
// src/backoffice/types/static/procedure-family.types.ts
|
|
91
|
-
var ProcedureFamily = /* @__PURE__ */ ((ProcedureFamily2) => {
|
|
92
|
-
ProcedureFamily2["AESTHETICS"] = "aesthetics";
|
|
93
|
-
ProcedureFamily2["SURGERY"] = "surgery";
|
|
94
|
-
return ProcedureFamily2;
|
|
95
|
-
})(ProcedureFamily || {});
|
|
96
|
-
|
|
97
|
-
// src/backoffice/types/static/treatment-benefit.types.ts
|
|
98
|
-
var TreatmentBenefit = /* @__PURE__ */ ((TreatmentBenefit2) => {
|
|
99
|
-
TreatmentBenefit2["WRINKLE_REDUCTION"] = "wrinkle_reduction";
|
|
100
|
-
TreatmentBenefit2["SKIN_TIGHTENING"] = "skin_tightening";
|
|
101
|
-
TreatmentBenefit2["COLLAGEN_PRODUCTION"] = "collagen_production";
|
|
102
|
-
TreatmentBenefit2["ACNE_REDUCTION"] = "acne_reduction";
|
|
103
|
-
TreatmentBenefit2["SCAR_REDUCTION"] = "scar_reduction";
|
|
104
|
-
TreatmentBenefit2["PIGMENTATION_IMPROVEMENT"] = "pigmentation_improvement";
|
|
105
|
-
TreatmentBenefit2["HAIR_REMOVAL"] = "hair_removal";
|
|
106
|
-
TreatmentBenefit2["MUSCLE_TONING"] = "muscle_toning";
|
|
107
|
-
TreatmentBenefit2["FAT_REDUCTION"] = "fat_reduction";
|
|
108
|
-
TreatmentBenefit2["CELLULITE_REDUCTION"] = "cellulite_reduction";
|
|
109
|
-
TreatmentBenefit2["SKIN_REJUVENATION"] = "skin_rejuvenation";
|
|
110
|
-
TreatmentBenefit2["PORE_REDUCTION"] = "pore_reduction";
|
|
111
|
-
TreatmentBenefit2["TEXTURE_IMPROVEMENT"] = "texture_improvement";
|
|
112
|
-
TreatmentBenefit2["HYDRATION_BOOST"] = "hydration_boost";
|
|
113
|
-
TreatmentBenefit2["CIRCULATION_IMPROVEMENT"] = "circulation_improvement";
|
|
114
|
-
return TreatmentBenefit2;
|
|
115
|
-
})(TreatmentBenefit || {});
|
|
116
|
-
|
|
117
|
-
// src/types/documentation-templates/index.ts
|
|
118
|
-
var DOCUMENTATION_TEMPLATES_COLLECTION = "documentation-templates";
|
|
119
|
-
var DocumentElementType = /* @__PURE__ */ ((DocumentElementType2) => {
|
|
120
|
-
DocumentElementType2["HEADING"] = "heading";
|
|
121
|
-
DocumentElementType2["PARAGRAPH"] = "paragraph";
|
|
122
|
-
DocumentElementType2["LIST"] = "list";
|
|
123
|
-
DocumentElementType2["DYNAMIC_TEXT"] = "dynamic_text";
|
|
124
|
-
DocumentElementType2["BINARY_CHOICE"] = "binary_choice";
|
|
125
|
-
DocumentElementType2["MULTIPLE_CHOICE"] = "multiple_choice";
|
|
126
|
-
DocumentElementType2["SINGLE_CHOICE"] = "single_choice";
|
|
127
|
-
DocumentElementType2["RATING_SCALE"] = "rating_scale";
|
|
128
|
-
DocumentElementType2["TEXT_INPUT"] = "text_input";
|
|
129
|
-
DocumentElementType2["DATE_PICKER"] = "date_picker";
|
|
130
|
-
DocumentElementType2["SIGNATURE"] = "signature";
|
|
131
|
-
DocumentElementType2["DITIGAL_SIGNATURE"] = "digital_signature";
|
|
132
|
-
DocumentElementType2["FILE_UPLOAD"] = "file_upload";
|
|
133
|
-
return DocumentElementType2;
|
|
134
|
-
})(DocumentElementType || {});
|
|
135
|
-
var ListType = /* @__PURE__ */ ((ListType2) => {
|
|
136
|
-
ListType2["ORDERED"] = "ordered";
|
|
137
|
-
ListType2["UNORDERED"] = "unordered";
|
|
138
|
-
return ListType2;
|
|
139
|
-
})(ListType || {});
|
|
140
|
-
var HeadingLevel = /* @__PURE__ */ ((HeadingLevel2) => {
|
|
141
|
-
HeadingLevel2["H1"] = "h1";
|
|
142
|
-
HeadingLevel2["H2"] = "h2";
|
|
143
|
-
HeadingLevel2["H3"] = "h3";
|
|
144
|
-
HeadingLevel2["H4"] = "h4";
|
|
145
|
-
HeadingLevel2["H5"] = "h5";
|
|
146
|
-
HeadingLevel2["H6"] = "h6";
|
|
147
|
-
return HeadingLevel2;
|
|
148
|
-
})(HeadingLevel || {});
|
|
149
|
-
var DynamicVariable = /* @__PURE__ */ ((DynamicVariable2) => {
|
|
150
|
-
DynamicVariable2["PATIENT_NAME"] = "$[PATIENT_NAME]";
|
|
151
|
-
DynamicVariable2["DOCTOR_NAME"] = "$[DOCTOR_NAME]";
|
|
152
|
-
DynamicVariable2["CLINIC_NAME"] = "$[CLINIC_NAME]";
|
|
153
|
-
DynamicVariable2["PATIENT_BIRTHDAY"] = "$[PATIENT_BIRTHDAY]";
|
|
154
|
-
DynamicVariable2["APPOINTMENT_DATE"] = "$[APPOINTMENT_DATE]";
|
|
155
|
-
DynamicVariable2["CURRENT_DATE"] = "$[CURRENT_DATE]";
|
|
156
|
-
DynamicVariable2["PROCEDURE_NAME"] = "$[PROCEDURE_NAME]";
|
|
157
|
-
DynamicVariable2["PROCEDURE_DESCRIPTION"] = "$[PROCEDURE_DESCRIPTION]";
|
|
158
|
-
DynamicVariable2["PROCEDURE_COST"] = "$[PROCEDURE_COST]";
|
|
159
|
-
DynamicVariable2["PROCEDURE_DURATION"] = "$[PROCEDURE_DURATION]";
|
|
160
|
-
DynamicVariable2["PROCEDURE_RISK"] = "$[PROCEDURE_RISK]";
|
|
161
|
-
return DynamicVariable2;
|
|
162
|
-
})(DynamicVariable || {});
|
|
163
|
-
var FilledDocumentStatus = /* @__PURE__ */ ((FilledDocumentStatus2) => {
|
|
164
|
-
FilledDocumentStatus2["DRAFT"] = "draft";
|
|
165
|
-
FilledDocumentStatus2["SKIPPED"] = "skipped";
|
|
166
|
-
FilledDocumentStatus2["PENDING"] = "pending";
|
|
167
|
-
FilledDocumentStatus2["COMPLETED"] = "completed";
|
|
168
|
-
FilledDocumentStatus2["SIGNED"] = "signed";
|
|
169
|
-
FilledDocumentStatus2["REJECTED"] = "rejected";
|
|
170
|
-
return FilledDocumentStatus2;
|
|
171
|
-
})(FilledDocumentStatus || {});
|
|
172
|
-
|
|
173
|
-
// src/backoffice/constants/certification.constants.ts
|
|
174
|
-
var DEFAULT_CERTIFICATION_REQUIREMENT = {
|
|
175
|
-
minimumLevel: "aesthetician" /* AESTHETICIAN */,
|
|
176
|
-
requiredSpecialties: []
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
// src/backoffice/errors/backoffice.errors.ts
|
|
180
|
-
var BackofficeError = class extends Error {
|
|
181
|
-
constructor(message) {
|
|
182
|
-
super(message);
|
|
183
|
-
this.name = "BackofficeError";
|
|
184
|
-
}
|
|
185
|
-
};
|
|
186
|
-
var CategoryError = class extends BackofficeError {
|
|
187
|
-
constructor(message) {
|
|
188
|
-
super(message);
|
|
189
|
-
this.name = "CategoryError";
|
|
190
|
-
}
|
|
191
|
-
};
|
|
192
|
-
var CategoryNotFoundError = class extends CategoryError {
|
|
193
|
-
constructor(id) {
|
|
194
|
-
super(`Kategorija sa ID-em ${id} nije prona\u0111ena`);
|
|
195
|
-
this.name = "CategoryNotFoundError";
|
|
196
|
-
}
|
|
197
|
-
};
|
|
198
|
-
var InvalidCategoryDataError = class extends CategoryError {
|
|
199
|
-
constructor(message) {
|
|
200
|
-
super(`Neva\u017Ee\u0107i podaci za kategoriju: ${message}`);
|
|
201
|
-
this.name = "InvalidCategoryDataError";
|
|
202
|
-
}
|
|
203
|
-
};
|
|
204
|
-
var SubcategoryError = class extends BackofficeError {
|
|
205
|
-
constructor(message) {
|
|
206
|
-
super(message);
|
|
207
|
-
this.name = "SubcategoryError";
|
|
208
|
-
}
|
|
209
|
-
};
|
|
210
|
-
var SubcategoryNotFoundError = class extends SubcategoryError {
|
|
211
|
-
constructor(id) {
|
|
212
|
-
super(`Podkategorija sa ID-em ${id} nije prona\u0111ena`);
|
|
213
|
-
this.name = "SubcategoryNotFoundError";
|
|
214
|
-
}
|
|
215
|
-
};
|
|
216
|
-
var InvalidSubcategoryDataError = class extends SubcategoryError {
|
|
217
|
-
constructor(message) {
|
|
218
|
-
super(`Neva\u017Ee\u0107i podaci za podkategoriju: ${message}`);
|
|
219
|
-
this.name = "InvalidSubcategoryDataError";
|
|
220
|
-
}
|
|
221
|
-
};
|
|
222
|
-
var TechnologyError = class extends BackofficeError {
|
|
223
|
-
constructor(message) {
|
|
224
|
-
super(message);
|
|
225
|
-
this.name = "TechnologyError";
|
|
226
|
-
}
|
|
227
|
-
};
|
|
228
|
-
var TechnologyNotFoundError = class extends TechnologyError {
|
|
229
|
-
constructor(id) {
|
|
230
|
-
super(`Tehnologija sa ID-em ${id} nije prona\u0111ena`);
|
|
231
|
-
this.name = "TechnologyNotFoundError";
|
|
16
|
+
// src/services/base.service.ts
|
|
17
|
+
import { getStorage } from "firebase/storage";
|
|
18
|
+
var BaseService = class {
|
|
19
|
+
constructor(db, auth, app) {
|
|
20
|
+
this.db = db;
|
|
21
|
+
this.auth = auth;
|
|
22
|
+
this.app = app;
|
|
23
|
+
this.storage = getStorage(app);
|
|
232
24
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Generiše jedinstveni ID za dokumente
|
|
27
|
+
* Format: xxxxxxxxxxxx-timestamp
|
|
28
|
+
* Gde je x random karakter (broj ili slovo)
|
|
29
|
+
*/
|
|
30
|
+
generateId() {
|
|
31
|
+
const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
|
32
|
+
const timestamp = Date.now().toString(36);
|
|
33
|
+
const randomPart = Array.from(
|
|
34
|
+
{ length: 12 },
|
|
35
|
+
() => chars.charAt(Math.floor(Math.random() * chars.length))
|
|
36
|
+
).join("");
|
|
37
|
+
return `${randomPart}-${timestamp}`;
|
|
238
38
|
}
|
|
239
39
|
};
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
40
|
+
|
|
41
|
+
// src/backoffice/services/brand.service.ts
|
|
42
|
+
var BrandService = class extends BaseService {
|
|
43
|
+
/**
|
|
44
|
+
* Gets reference to brands collection
|
|
45
|
+
*/
|
|
46
|
+
getBrandsRef() {
|
|
47
|
+
return collection(this.db, BRANDS_COLLECTION);
|
|
244
48
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Creates a new brand
|
|
51
|
+
*/
|
|
52
|
+
async create(brand) {
|
|
53
|
+
const now = /* @__PURE__ */ new Date();
|
|
54
|
+
const newBrand = {
|
|
55
|
+
...brand,
|
|
56
|
+
createdAt: now,
|
|
57
|
+
updatedAt: now,
|
|
58
|
+
isActive: true
|
|
59
|
+
};
|
|
60
|
+
const docRef = await addDoc(this.getBrandsRef(), newBrand);
|
|
61
|
+
return { id: docRef.id, ...newBrand };
|
|
250
62
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
this.
|
|
63
|
+
/**
|
|
64
|
+
* Gets all active brands
|
|
65
|
+
*/
|
|
66
|
+
async getAll() {
|
|
67
|
+
const q = query(this.getBrandsRef(), where("isActive", "==", true));
|
|
68
|
+
const snapshot = await getDocs(q);
|
|
69
|
+
return snapshot.docs.map(
|
|
70
|
+
(doc10) => ({
|
|
71
|
+
id: doc10.id,
|
|
72
|
+
...doc10.data()
|
|
73
|
+
})
|
|
74
|
+
);
|
|
256
75
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Updates a brand
|
|
78
|
+
*/
|
|
79
|
+
async update(brandId, brand) {
|
|
80
|
+
const updateData = {
|
|
81
|
+
...brand,
|
|
82
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
83
|
+
};
|
|
84
|
+
const docRef = doc(this.getBrandsRef(), brandId);
|
|
85
|
+
await updateDoc(docRef, updateData);
|
|
86
|
+
return this.getById(brandId);
|
|
262
87
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
this.
|
|
88
|
+
/**
|
|
89
|
+
* Soft deletes a brand
|
|
90
|
+
*/
|
|
91
|
+
async delete(brandId) {
|
|
92
|
+
await this.update(brandId, {
|
|
93
|
+
isActive: false
|
|
94
|
+
});
|
|
268
95
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
this.
|
|
96
|
+
/**
|
|
97
|
+
* Gets a brand by ID
|
|
98
|
+
*/
|
|
99
|
+
async getById(brandId) {
|
|
100
|
+
const docRef = doc(this.getBrandsRef(), brandId);
|
|
101
|
+
const docSnap = await getDoc(docRef);
|
|
102
|
+
if (!docSnap.exists()) return null;
|
|
103
|
+
return {
|
|
104
|
+
id: docSnap.id,
|
|
105
|
+
...docSnap.data()
|
|
106
|
+
};
|
|
274
107
|
}
|
|
275
108
|
};
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
109
|
+
|
|
110
|
+
// src/backoffice/services/category.service.ts
|
|
111
|
+
import {
|
|
112
|
+
addDoc as addDoc2,
|
|
113
|
+
collection as collection2,
|
|
114
|
+
doc as doc2,
|
|
115
|
+
getDoc as getDoc2,
|
|
116
|
+
getDocs as getDocs2,
|
|
117
|
+
query as query2,
|
|
118
|
+
updateDoc as updateDoc2,
|
|
119
|
+
where as where2
|
|
120
|
+
} from "firebase/firestore";
|
|
121
|
+
|
|
122
|
+
// src/backoffice/types/category.types.ts
|
|
123
|
+
var CATEGORIES_COLLECTION = "backoffice_categories";
|
|
124
|
+
|
|
125
|
+
// src/backoffice/services/category.service.ts
|
|
126
|
+
var CategoryService = class extends BaseService {
|
|
127
|
+
/**
|
|
128
|
+
* Referenca na Firestore kolekciju kategorija
|
|
129
|
+
*/
|
|
130
|
+
get categoriesRef() {
|
|
131
|
+
return collection2(this.db, CATEGORIES_COLLECTION);
|
|
280
132
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
133
|
+
/**
|
|
134
|
+
* Kreira novu kategoriju u sistemu
|
|
135
|
+
* @param category - Podaci za novu kategoriju
|
|
136
|
+
* @returns Kreirana kategorija sa generisanim ID-em
|
|
137
|
+
*/
|
|
138
|
+
async create(category) {
|
|
139
|
+
const now = /* @__PURE__ */ new Date();
|
|
140
|
+
const newCategory = {
|
|
141
|
+
...category,
|
|
142
|
+
createdAt: now,
|
|
143
|
+
updatedAt: now,
|
|
144
|
+
isActive: true
|
|
145
|
+
};
|
|
146
|
+
const docRef = await addDoc2(this.categoriesRef, newCategory);
|
|
147
|
+
return { id: docRef.id, ...newCategory };
|
|
286
148
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
149
|
+
/**
|
|
150
|
+
* Vraća sve aktivne kategorije
|
|
151
|
+
* @returns Lista aktivnih kategorija
|
|
152
|
+
*/
|
|
153
|
+
async getAll() {
|
|
154
|
+
const q = query2(this.categoriesRef, where2("isActive", "==", true));
|
|
155
|
+
const snapshot = await getDocs2(q);
|
|
156
|
+
return snapshot.docs.map(
|
|
157
|
+
(doc10) => ({
|
|
158
|
+
id: doc10.id,
|
|
159
|
+
...doc10.data()
|
|
160
|
+
})
|
|
161
|
+
);
|
|
292
162
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
163
|
+
/**
|
|
164
|
+
* Vraća sve aktivne kategorije za određenu familiju procedura
|
|
165
|
+
* @param family - Familija procedura (aesthetics/surgery)
|
|
166
|
+
* @returns Lista kategorija koje pripadaju traženoj familiji
|
|
167
|
+
*/
|
|
168
|
+
async getAllByFamily(family) {
|
|
169
|
+
const q = query2(
|
|
170
|
+
this.categoriesRef,
|
|
171
|
+
where2("family", "==", family),
|
|
172
|
+
where2("isActive", "==", true)
|
|
173
|
+
);
|
|
174
|
+
const snapshot = await getDocs2(q);
|
|
175
|
+
return snapshot.docs.map(
|
|
176
|
+
(doc10) => ({
|
|
177
|
+
id: doc10.id,
|
|
178
|
+
...doc10.data()
|
|
179
|
+
})
|
|
180
|
+
);
|
|
298
181
|
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
182
|
+
/**
|
|
183
|
+
* Ažurira postojeću kategoriju
|
|
184
|
+
* @param id - ID kategorije koja se ažurira
|
|
185
|
+
* @param category - Novi podaci za kategoriju
|
|
186
|
+
* @returns Ažurirana kategorija
|
|
187
|
+
*/
|
|
188
|
+
async update(id, category) {
|
|
189
|
+
const updateData = {
|
|
190
|
+
...category,
|
|
191
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
192
|
+
};
|
|
193
|
+
const docRef = doc2(this.categoriesRef, id);
|
|
194
|
+
await updateDoc2(docRef, updateData);
|
|
195
|
+
return this.getById(id);
|
|
304
196
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
197
|
+
/**
|
|
198
|
+
* Soft delete kategorije (postavlja isActive na false)
|
|
199
|
+
* @param id - ID kategorije koja se briše
|
|
200
|
+
*/
|
|
201
|
+
async delete(id) {
|
|
202
|
+
await this.update(id, { isActive: false });
|
|
310
203
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
204
|
+
/**
|
|
205
|
+
* Vraća kategoriju po ID-u
|
|
206
|
+
* @param id - ID tražene kategorije
|
|
207
|
+
* @returns Kategorija ili null ako ne postoji
|
|
208
|
+
*/
|
|
209
|
+
async getById(id) {
|
|
210
|
+
const docRef = doc2(this.categoriesRef, id);
|
|
211
|
+
const docSnap = await getDoc2(docRef);
|
|
212
|
+
if (!docSnap.exists()) return null;
|
|
213
|
+
return {
|
|
214
|
+
id: docSnap.id,
|
|
215
|
+
...docSnap.data()
|
|
216
|
+
};
|
|
316
217
|
}
|
|
317
218
|
};
|
|
318
219
|
|
|
319
|
-
// src/
|
|
320
|
-
import {
|
|
220
|
+
// src/services/documentation-templates/documentation-template.service.ts
|
|
221
|
+
import {
|
|
222
|
+
collection as collection3,
|
|
223
|
+
doc as doc3,
|
|
224
|
+
getDoc as getDoc3,
|
|
225
|
+
getDocs as getDocs3,
|
|
226
|
+
setDoc,
|
|
227
|
+
updateDoc as updateDoc3,
|
|
228
|
+
deleteDoc,
|
|
229
|
+
query as query3,
|
|
230
|
+
where as where3,
|
|
231
|
+
orderBy,
|
|
232
|
+
limit,
|
|
233
|
+
startAfter
|
|
234
|
+
} from "firebase/firestore";
|
|
235
|
+
|
|
236
|
+
// src/types/documentation-templates/index.ts
|
|
237
|
+
var DOCUMENTATION_TEMPLATES_COLLECTION = "documentation-templates";
|
|
238
|
+
var DocumentElementType = /* @__PURE__ */ ((DocumentElementType2) => {
|
|
239
|
+
DocumentElementType2["HEADING"] = "heading";
|
|
240
|
+
DocumentElementType2["PARAGRAPH"] = "paragraph";
|
|
241
|
+
DocumentElementType2["LIST"] = "list";
|
|
242
|
+
DocumentElementType2["DYNAMIC_TEXT"] = "dynamic_text";
|
|
243
|
+
DocumentElementType2["BINARY_CHOICE"] = "binary_choice";
|
|
244
|
+
DocumentElementType2["MULTIPLE_CHOICE"] = "multiple_choice";
|
|
245
|
+
DocumentElementType2["SINGLE_CHOICE"] = "single_choice";
|
|
246
|
+
DocumentElementType2["RATING_SCALE"] = "rating_scale";
|
|
247
|
+
DocumentElementType2["TEXT_INPUT"] = "text_input";
|
|
248
|
+
DocumentElementType2["DATE_PICKER"] = "date_picker";
|
|
249
|
+
DocumentElementType2["SIGNATURE"] = "signature";
|
|
250
|
+
DocumentElementType2["DITIGAL_SIGNATURE"] = "digital_signature";
|
|
251
|
+
DocumentElementType2["FILE_UPLOAD"] = "file_upload";
|
|
252
|
+
return DocumentElementType2;
|
|
253
|
+
})(DocumentElementType || {});
|
|
254
|
+
var ListType = /* @__PURE__ */ ((ListType2) => {
|
|
255
|
+
ListType2["ORDERED"] = "ordered";
|
|
256
|
+
ListType2["UNORDERED"] = "unordered";
|
|
257
|
+
return ListType2;
|
|
258
|
+
})(ListType || {});
|
|
259
|
+
var HeadingLevel = /* @__PURE__ */ ((HeadingLevel2) => {
|
|
260
|
+
HeadingLevel2["H1"] = "h1";
|
|
261
|
+
HeadingLevel2["H2"] = "h2";
|
|
262
|
+
HeadingLevel2["H3"] = "h3";
|
|
263
|
+
HeadingLevel2["H4"] = "h4";
|
|
264
|
+
HeadingLevel2["H5"] = "h5";
|
|
265
|
+
HeadingLevel2["H6"] = "h6";
|
|
266
|
+
return HeadingLevel2;
|
|
267
|
+
})(HeadingLevel || {});
|
|
268
|
+
var DynamicVariable = /* @__PURE__ */ ((DynamicVariable2) => {
|
|
269
|
+
DynamicVariable2["PATIENT_NAME"] = "$[PATIENT_NAME]";
|
|
270
|
+
DynamicVariable2["DOCTOR_NAME"] = "$[DOCTOR_NAME]";
|
|
271
|
+
DynamicVariable2["CLINIC_NAME"] = "$[CLINIC_NAME]";
|
|
272
|
+
DynamicVariable2["PATIENT_BIRTHDAY"] = "$[PATIENT_BIRTHDAY]";
|
|
273
|
+
DynamicVariable2["APPOINTMENT_DATE"] = "$[APPOINTMENT_DATE]";
|
|
274
|
+
DynamicVariable2["CURRENT_DATE"] = "$[CURRENT_DATE]";
|
|
275
|
+
DynamicVariable2["PROCEDURE_NAME"] = "$[PROCEDURE_NAME]";
|
|
276
|
+
DynamicVariable2["PROCEDURE_DESCRIPTION"] = "$[PROCEDURE_DESCRIPTION]";
|
|
277
|
+
DynamicVariable2["PROCEDURE_COST"] = "$[PROCEDURE_COST]";
|
|
278
|
+
DynamicVariable2["PROCEDURE_DURATION"] = "$[PROCEDURE_DURATION]";
|
|
279
|
+
DynamicVariable2["PROCEDURE_RISK"] = "$[PROCEDURE_RISK]";
|
|
280
|
+
return DynamicVariable2;
|
|
281
|
+
})(DynamicVariable || {});
|
|
282
|
+
var FilledDocumentStatus = /* @__PURE__ */ ((FilledDocumentStatus2) => {
|
|
283
|
+
FilledDocumentStatus2["DRAFT"] = "draft";
|
|
284
|
+
FilledDocumentStatus2["SKIPPED"] = "skipped";
|
|
285
|
+
FilledDocumentStatus2["PENDING"] = "pending";
|
|
286
|
+
FilledDocumentStatus2["COMPLETED"] = "completed";
|
|
287
|
+
FilledDocumentStatus2["SIGNED"] = "signed";
|
|
288
|
+
FilledDocumentStatus2["REJECTED"] = "rejected";
|
|
289
|
+
return FilledDocumentStatus2;
|
|
290
|
+
})(FilledDocumentStatus || {});
|
|
321
291
|
|
|
322
292
|
// src/validations/documentation-templates/template.schema.ts
|
|
323
293
|
import { z } from "zod";
|
|
@@ -493,261 +463,478 @@ var updateFilledDocumentDataSchema = z.object({
|
|
|
493
463
|
status: filledDocumentStatusSchema.optional()
|
|
494
464
|
});
|
|
495
465
|
|
|
496
|
-
// src/
|
|
497
|
-
var
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
466
|
+
// src/services/documentation-templates/documentation-template.service.ts
|
|
467
|
+
var DocumentationTemplateService = class extends BaseService {
|
|
468
|
+
constructor() {
|
|
469
|
+
super(...arguments);
|
|
470
|
+
this.collectionRef = collection3(
|
|
471
|
+
this.db,
|
|
472
|
+
DOCUMENTATION_TEMPLATES_COLLECTION
|
|
473
|
+
);
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Create a new document template
|
|
477
|
+
* @param data - Template data
|
|
478
|
+
* @param userId - ID of the user creating the template
|
|
479
|
+
* @returns The created template
|
|
480
|
+
*/
|
|
481
|
+
async createTemplate(data, userId) {
|
|
482
|
+
const validatedData = createDocumentTemplateSchema.parse(data);
|
|
483
|
+
const templateId = this.generateId();
|
|
484
|
+
const elementsWithIds = validatedData.elements.map((element) => ({
|
|
485
|
+
...element,
|
|
486
|
+
id: this.generateId()
|
|
487
|
+
}));
|
|
488
|
+
const now = Date.now();
|
|
489
|
+
const template = {
|
|
490
|
+
id: templateId,
|
|
491
|
+
title: validatedData.title,
|
|
492
|
+
description: validatedData.description,
|
|
493
|
+
elements: elementsWithIds,
|
|
494
|
+
createdAt: now,
|
|
495
|
+
updatedAt: now,
|
|
496
|
+
createdBy: userId,
|
|
497
|
+
version: 1,
|
|
498
|
+
isActive: true,
|
|
499
|
+
tags: validatedData.tags || [],
|
|
500
|
+
isUserForm: validatedData.isUserForm || false,
|
|
501
|
+
isRequired: validatedData.isRequired || false,
|
|
502
|
+
sortingOrder: validatedData.sortingOrder || 0
|
|
503
|
+
};
|
|
504
|
+
const docRef = doc3(this.collectionRef, templateId);
|
|
505
|
+
await setDoc(docRef, template);
|
|
506
|
+
return template;
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Get a document template by ID
|
|
510
|
+
* @param templateId - ID of the template to retrieve
|
|
511
|
+
* @param version - Optional version number to retrieve (defaults to latest version)
|
|
512
|
+
* @returns The template or null if not found
|
|
513
|
+
*/
|
|
514
|
+
async getTemplateById(templateId, version) {
|
|
515
|
+
const docRef = doc3(this.collectionRef, templateId);
|
|
516
|
+
const docSnap = await getDoc3(docRef);
|
|
517
|
+
if (!docSnap.exists()) {
|
|
518
|
+
return null;
|
|
519
|
+
}
|
|
520
|
+
const currentTemplate = docSnap.data();
|
|
521
|
+
if (version === void 0) {
|
|
522
|
+
return currentTemplate;
|
|
523
|
+
}
|
|
524
|
+
if (currentTemplate.version === version) {
|
|
525
|
+
return currentTemplate;
|
|
526
|
+
}
|
|
527
|
+
try {
|
|
528
|
+
const versionTemplate = await this.getTemplateVersion(
|
|
529
|
+
templateId,
|
|
530
|
+
version
|
|
531
|
+
);
|
|
532
|
+
if (versionTemplate) {
|
|
533
|
+
return versionTemplate;
|
|
534
|
+
}
|
|
535
|
+
} catch (error) {
|
|
536
|
+
console.error(`Error getting template version ${version}:`, error);
|
|
537
|
+
}
|
|
538
|
+
return null;
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Update an existing document template
|
|
542
|
+
* @param templateId - ID of the template to update
|
|
543
|
+
* @param data - Updated template data
|
|
544
|
+
* @returns The updated template
|
|
545
|
+
*/
|
|
546
|
+
async updateTemplate(templateId, data) {
|
|
547
|
+
var _a, _b, _c;
|
|
548
|
+
const validatedData = updateDocumentTemplateSchema.parse(data);
|
|
549
|
+
console.log("Validated data", validatedData);
|
|
550
|
+
const template = await this.getTemplateById(templateId);
|
|
551
|
+
if (!template) {
|
|
552
|
+
throw new Error(`Template with ID ${templateId} not found`);
|
|
553
|
+
}
|
|
554
|
+
const versionsCollectionRef = collection3(
|
|
555
|
+
this.db,
|
|
556
|
+
`${DOCUMENTATION_TEMPLATES_COLLECTION}/${templateId}/versions`
|
|
557
|
+
);
|
|
558
|
+
const versionDocRef = doc3(
|
|
559
|
+
versionsCollectionRef,
|
|
560
|
+
template.version.toString()
|
|
561
|
+
);
|
|
562
|
+
await setDoc(versionDocRef, template);
|
|
563
|
+
let updatedElements = template.elements;
|
|
564
|
+
if (validatedData.elements) {
|
|
565
|
+
updatedElements = validatedData.elements.map((element) => ({
|
|
566
|
+
...element,
|
|
567
|
+
id: element.id || this.generateId()
|
|
568
|
+
}));
|
|
569
|
+
}
|
|
570
|
+
const updatePayload = {
|
|
571
|
+
elements: updatedElements,
|
|
572
|
+
updatedAt: Date.now(),
|
|
573
|
+
version: template.version + 1
|
|
574
|
+
};
|
|
575
|
+
if (validatedData.title !== void 0)
|
|
576
|
+
updatePayload.title = validatedData.title;
|
|
577
|
+
if (validatedData.description !== void 0)
|
|
578
|
+
updatePayload.description = validatedData.description;
|
|
579
|
+
if (validatedData.isActive !== void 0)
|
|
580
|
+
updatePayload.isActive = validatedData.isActive;
|
|
581
|
+
if (validatedData.tags !== void 0)
|
|
582
|
+
updatePayload.tags = validatedData.tags;
|
|
583
|
+
updatePayload.isUserForm = (_a = validatedData.isUserForm) != null ? _a : false;
|
|
584
|
+
updatePayload.isRequired = (_b = validatedData.isRequired) != null ? _b : false;
|
|
585
|
+
updatePayload.sortingOrder = (_c = validatedData.sortingOrder) != null ? _c : 0;
|
|
586
|
+
const docRef = doc3(this.collectionRef, templateId);
|
|
587
|
+
console.log("Update payload", updatePayload);
|
|
588
|
+
await updateDoc3(docRef, updatePayload);
|
|
589
|
+
return { ...template, ...updatePayload };
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
592
|
+
* Get a specific version of a template
|
|
593
|
+
* @param templateId - ID of the template
|
|
594
|
+
* @param versionNumber - Version number to retrieve
|
|
595
|
+
* @returns The template version or null if not found
|
|
596
|
+
*/
|
|
597
|
+
async getTemplateVersion(templateId, versionNumber) {
|
|
598
|
+
const versionDocRef = doc3(
|
|
599
|
+
this.db,
|
|
600
|
+
`${DOCUMENTATION_TEMPLATES_COLLECTION}/${templateId}/versions/${versionNumber}`
|
|
601
|
+
);
|
|
602
|
+
const versionDocSnap = await getDoc3(versionDocRef);
|
|
603
|
+
if (!versionDocSnap.exists()) {
|
|
604
|
+
return null;
|
|
605
|
+
}
|
|
606
|
+
return versionDocSnap.data();
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* Get all versions of a template
|
|
610
|
+
* @param templateId - ID of the template
|
|
611
|
+
* @returns Array of template versions
|
|
612
|
+
*/
|
|
613
|
+
async getTemplateOldVersions(templateId) {
|
|
614
|
+
const versionsCollectionRef = collection3(
|
|
615
|
+
this.db,
|
|
616
|
+
`${DOCUMENTATION_TEMPLATES_COLLECTION}/${templateId}/versions`
|
|
617
|
+
);
|
|
618
|
+
const q = query3(versionsCollectionRef, orderBy("version", "desc"));
|
|
619
|
+
const querySnapshot = await getDocs3(q);
|
|
620
|
+
const versions = [];
|
|
621
|
+
querySnapshot.forEach((doc10) => {
|
|
622
|
+
versions.push(doc10.data());
|
|
623
|
+
});
|
|
624
|
+
return versions;
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Delete a document template
|
|
628
|
+
* @param templateId - ID of the template to delete
|
|
629
|
+
*/
|
|
630
|
+
async deleteTemplate(templateId) {
|
|
631
|
+
const docRef = doc3(this.collectionRef, templateId);
|
|
632
|
+
await deleteDoc(docRef);
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Get all active templates
|
|
636
|
+
* @param pageSize - Number of templates to retrieve
|
|
637
|
+
* @param lastDoc - Last document from previous page for pagination
|
|
638
|
+
* @returns Array of templates and the last document for pagination
|
|
639
|
+
*/
|
|
640
|
+
async getActiveTemplates(pageSize = 20, lastDoc) {
|
|
641
|
+
let q = query3(
|
|
642
|
+
this.collectionRef,
|
|
643
|
+
where3("isActive", "==", true),
|
|
644
|
+
orderBy("updatedAt", "desc"),
|
|
645
|
+
limit(pageSize)
|
|
646
|
+
);
|
|
647
|
+
if (lastDoc) {
|
|
648
|
+
q = query3(q, startAfter(lastDoc));
|
|
649
|
+
}
|
|
650
|
+
const querySnapshot = await getDocs3(q);
|
|
651
|
+
const templates = [];
|
|
652
|
+
let lastVisible = null;
|
|
653
|
+
querySnapshot.forEach((doc10) => {
|
|
654
|
+
templates.push(doc10.data());
|
|
655
|
+
lastVisible = doc10;
|
|
656
|
+
});
|
|
657
|
+
return {
|
|
658
|
+
templates,
|
|
659
|
+
lastDoc: lastVisible
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
/**
|
|
663
|
+
* Get templates by tags
|
|
664
|
+
* @param tags - Tags to filter by
|
|
665
|
+
* @param pageSize - Number of templates to retrieve
|
|
666
|
+
* @param lastDoc - Last document from previous page for pagination
|
|
667
|
+
* @returns Array of templates and the last document for pagination
|
|
668
|
+
*/
|
|
669
|
+
async getTemplatesByTags(tags, pageSize = 20, lastDoc) {
|
|
670
|
+
let q = query3(
|
|
671
|
+
this.collectionRef,
|
|
672
|
+
where3("isActive", "==", true),
|
|
673
|
+
where3("tags", "array-contains-any", tags),
|
|
674
|
+
orderBy("updatedAt", "desc"),
|
|
675
|
+
limit(pageSize)
|
|
676
|
+
);
|
|
677
|
+
if (lastDoc) {
|
|
678
|
+
q = query3(q, startAfter(lastDoc));
|
|
679
|
+
}
|
|
680
|
+
const querySnapshot = await getDocs3(q);
|
|
681
|
+
const templates = [];
|
|
682
|
+
let lastVisible = null;
|
|
683
|
+
querySnapshot.forEach((doc10) => {
|
|
684
|
+
templates.push(doc10.data());
|
|
685
|
+
lastVisible = doc10;
|
|
686
|
+
});
|
|
687
|
+
return {
|
|
688
|
+
templates,
|
|
689
|
+
lastDoc: lastVisible
|
|
690
|
+
};
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* Get templates created by a specific user
|
|
694
|
+
* @param userId - ID of the user who created the templates
|
|
695
|
+
* @param pageSize - Number of templates to retrieve
|
|
696
|
+
* @param lastDoc - Last document from previous page for pagination
|
|
697
|
+
* @returns Array of templates and the last document for pagination
|
|
698
|
+
*/
|
|
699
|
+
async getTemplatesByCreator(userId, pageSize = 20, lastDoc) {
|
|
700
|
+
let q = query3(
|
|
701
|
+
this.collectionRef,
|
|
702
|
+
where3("createdBy", "==", userId),
|
|
703
|
+
orderBy("updatedAt", "desc"),
|
|
704
|
+
limit(pageSize)
|
|
705
|
+
);
|
|
706
|
+
if (lastDoc) {
|
|
707
|
+
q = query3(q, startAfter(lastDoc));
|
|
708
|
+
}
|
|
709
|
+
const querySnapshot = await getDocs3(q);
|
|
710
|
+
const templates = [];
|
|
711
|
+
let lastVisible = null;
|
|
712
|
+
querySnapshot.forEach((doc10) => {
|
|
713
|
+
templates.push(doc10.data());
|
|
714
|
+
lastVisible = doc10;
|
|
715
|
+
});
|
|
716
|
+
return {
|
|
717
|
+
templates,
|
|
718
|
+
lastDoc: lastVisible
|
|
719
|
+
};
|
|
720
|
+
}
|
|
721
|
+
/**
|
|
722
|
+
* Get all templates for selection with optional filtering
|
|
723
|
+
* @param options - Filtering options
|
|
724
|
+
* @returns Array of templates
|
|
725
|
+
*/
|
|
726
|
+
async getAllTemplatesForSelection(options) {
|
|
727
|
+
let q = query3(
|
|
728
|
+
this.collectionRef,
|
|
729
|
+
where3("isActive", "==", true),
|
|
730
|
+
orderBy("updatedAt", "desc")
|
|
731
|
+
);
|
|
732
|
+
if ((options == null ? void 0 : options.isUserForm) !== void 0) {
|
|
733
|
+
q = query3(q, where3("isUserForm", "==", options.isUserForm));
|
|
734
|
+
}
|
|
735
|
+
if ((options == null ? void 0 : options.isRequired) !== void 0) {
|
|
736
|
+
q = query3(q, where3("isRequired", "==", options.isRequired));
|
|
737
|
+
}
|
|
738
|
+
const querySnapshot = await getDocs3(q);
|
|
739
|
+
const templates = [];
|
|
740
|
+
querySnapshot.forEach((doc10) => {
|
|
741
|
+
templates.push(doc10.data());
|
|
742
|
+
});
|
|
743
|
+
return templates;
|
|
744
|
+
}
|
|
745
|
+
};
|
|
746
|
+
|
|
747
|
+
// src/services/documentation-templates/filled-document.service.ts
|
|
748
|
+
import {
|
|
749
|
+
collection as collection5,
|
|
750
|
+
doc as doc5,
|
|
751
|
+
getDoc as getDoc5,
|
|
752
|
+
getDocs as getDocs5,
|
|
753
|
+
setDoc as setDoc3,
|
|
754
|
+
updateDoc as updateDoc5,
|
|
755
|
+
query as query5,
|
|
756
|
+
orderBy as orderBy3,
|
|
757
|
+
limit as limit3,
|
|
758
|
+
startAfter as startAfter2
|
|
759
|
+
} from "firebase/firestore";
|
|
562
760
|
|
|
563
|
-
// src/
|
|
761
|
+
// src/services/media/media.service.ts
|
|
762
|
+
import { Timestamp as Timestamp2 } from "firebase/firestore";
|
|
564
763
|
import {
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
764
|
+
ref,
|
|
765
|
+
uploadBytes,
|
|
766
|
+
getDownloadURL,
|
|
767
|
+
deleteObject,
|
|
768
|
+
getBytes
|
|
769
|
+
} from "firebase/storage";
|
|
770
|
+
import {
|
|
771
|
+
doc as doc4,
|
|
772
|
+
getDoc as getDoc4,
|
|
773
|
+
setDoc as setDoc2,
|
|
774
|
+
updateDoc as updateDoc4,
|
|
775
|
+
collection as collection4,
|
|
776
|
+
query as query4,
|
|
777
|
+
where as where4,
|
|
778
|
+
limit as limit2,
|
|
779
|
+
getDocs as getDocs4,
|
|
780
|
+
deleteDoc as deleteDoc2,
|
|
781
|
+
orderBy as orderBy2
|
|
573
782
|
} from "firebase/firestore";
|
|
574
783
|
|
|
575
|
-
// src/services/
|
|
576
|
-
|
|
577
|
-
|
|
784
|
+
// src/backoffice/services/documentation-template.service.ts
|
|
785
|
+
var DocumentationTemplateService2 = class {
|
|
786
|
+
/**
|
|
787
|
+
* Constructor for DocumentationTemplateService
|
|
788
|
+
* @param db - Firestore instance
|
|
789
|
+
* @param auth - Firebase Auth instance
|
|
790
|
+
* @param app - Firebase App instance
|
|
791
|
+
*/
|
|
578
792
|
constructor(db, auth, app) {
|
|
579
|
-
this.
|
|
580
|
-
this.auth = auth;
|
|
581
|
-
this.app = app;
|
|
582
|
-
this.storage = getStorage(app);
|
|
793
|
+
this.apiService = new DocumentationTemplateService(db, auth, app);
|
|
583
794
|
}
|
|
584
795
|
/**
|
|
585
|
-
*
|
|
586
|
-
*
|
|
587
|
-
*
|
|
796
|
+
* Create a new document template
|
|
797
|
+
* @param data - Template data
|
|
798
|
+
* @param userId - ID of the user creating the template
|
|
799
|
+
* @returns The created template
|
|
588
800
|
*/
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
const timestamp = Date.now().toString(36);
|
|
592
|
-
const randomPart = Array.from(
|
|
593
|
-
{ length: 12 },
|
|
594
|
-
() => chars.charAt(Math.floor(Math.random() * chars.length))
|
|
595
|
-
).join("");
|
|
596
|
-
return `${randomPart}-${timestamp}`;
|
|
801
|
+
async createTemplate(data, userId) {
|
|
802
|
+
return this.apiService.createTemplate(data, userId);
|
|
597
803
|
}
|
|
598
|
-
};
|
|
599
|
-
|
|
600
|
-
// src/backoffice/services/category.service.ts
|
|
601
|
-
var CategoryService = class extends BaseService {
|
|
602
804
|
/**
|
|
603
|
-
*
|
|
805
|
+
* Get a document template by ID
|
|
806
|
+
* @param templateId - ID of the template to retrieve
|
|
807
|
+
* @param version - Optional version number to retrieve (defaults to latest version)
|
|
808
|
+
* @returns The template or null if not found
|
|
604
809
|
*/
|
|
605
|
-
|
|
606
|
-
return
|
|
810
|
+
async getTemplateById(templateId, version) {
|
|
811
|
+
return this.apiService.getTemplateById(templateId, version);
|
|
607
812
|
}
|
|
608
813
|
/**
|
|
609
|
-
*
|
|
610
|
-
* @param
|
|
611
|
-
* @
|
|
814
|
+
* Update an existing document template
|
|
815
|
+
* @param templateId - ID of the template to update
|
|
816
|
+
* @param data - Updated template data
|
|
817
|
+
* @returns The updated template
|
|
612
818
|
*/
|
|
613
|
-
async
|
|
614
|
-
|
|
615
|
-
const newCategory = {
|
|
616
|
-
...category,
|
|
617
|
-
createdAt: now,
|
|
618
|
-
updatedAt: now,
|
|
619
|
-
isActive: true
|
|
620
|
-
};
|
|
621
|
-
const docRef = await addDoc(this.categoriesRef, newCategory);
|
|
622
|
-
return { id: docRef.id, ...newCategory };
|
|
819
|
+
async updateTemplate(templateId, data) {
|
|
820
|
+
return this.apiService.updateTemplate(templateId, data);
|
|
623
821
|
}
|
|
624
822
|
/**
|
|
625
|
-
*
|
|
626
|
-
* @
|
|
823
|
+
* Delete a document template
|
|
824
|
+
* @param templateId - ID of the template to delete
|
|
627
825
|
*/
|
|
628
|
-
async
|
|
629
|
-
|
|
630
|
-
const snapshot = await getDocs(q);
|
|
631
|
-
return snapshot.docs.map(
|
|
632
|
-
(doc10) => ({
|
|
633
|
-
id: doc10.id,
|
|
634
|
-
...doc10.data()
|
|
635
|
-
})
|
|
636
|
-
);
|
|
826
|
+
async deleteTemplate(templateId) {
|
|
827
|
+
return this.apiService.deleteTemplate(templateId);
|
|
637
828
|
}
|
|
638
829
|
/**
|
|
639
|
-
*
|
|
640
|
-
* @param
|
|
641
|
-
* @
|
|
830
|
+
* Get all active templates
|
|
831
|
+
* @param pageSize - Number of templates to retrieve
|
|
832
|
+
* @param lastDoc - Last document from previous page for pagination
|
|
833
|
+
* @returns Array of templates and the last document for pagination
|
|
642
834
|
*/
|
|
643
|
-
async
|
|
644
|
-
|
|
645
|
-
this.categoriesRef,
|
|
646
|
-
where("family", "==", family),
|
|
647
|
-
where("isActive", "==", true)
|
|
648
|
-
);
|
|
649
|
-
const snapshot = await getDocs(q);
|
|
650
|
-
return snapshot.docs.map(
|
|
651
|
-
(doc10) => ({
|
|
652
|
-
id: doc10.id,
|
|
653
|
-
...doc10.data()
|
|
654
|
-
})
|
|
655
|
-
);
|
|
835
|
+
async getActiveTemplates(pageSize = 20, lastDoc) {
|
|
836
|
+
return this.apiService.getActiveTemplates(pageSize, lastDoc);
|
|
656
837
|
}
|
|
657
838
|
/**
|
|
658
|
-
*
|
|
659
|
-
* @param
|
|
660
|
-
* @param
|
|
661
|
-
* @
|
|
839
|
+
* Get templates by tags
|
|
840
|
+
* @param tags - Tags to filter by
|
|
841
|
+
* @param pageSize - Number of templates to retrieve
|
|
842
|
+
* @param lastDoc - Last document from previous page for pagination
|
|
843
|
+
* @returns Array of templates and the last document for pagination
|
|
662
844
|
*/
|
|
663
|
-
async
|
|
664
|
-
|
|
665
|
-
...category,
|
|
666
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
667
|
-
};
|
|
668
|
-
const docRef = doc(this.categoriesRef, id);
|
|
669
|
-
await updateDoc(docRef, updateData);
|
|
670
|
-
return this.getById(id);
|
|
845
|
+
async getTemplatesByTags(tags, pageSize = 20, lastDoc) {
|
|
846
|
+
return this.apiService.getTemplatesByTags(tags, pageSize, lastDoc);
|
|
671
847
|
}
|
|
672
848
|
/**
|
|
673
|
-
*
|
|
674
|
-
* @param
|
|
849
|
+
* Get templates created by a specific user
|
|
850
|
+
* @param userId - ID of the user who created the templates
|
|
851
|
+
* @param pageSize - Number of templates to retrieve
|
|
852
|
+
* @param lastDoc - Last document from previous page for pagination
|
|
853
|
+
* @returns Array of templates and the last document for pagination
|
|
675
854
|
*/
|
|
676
|
-
async
|
|
677
|
-
|
|
855
|
+
async getTemplatesByCreator(userId, pageSize = 20, lastDoc) {
|
|
856
|
+
return this.apiService.getTemplatesByCreator(userId, pageSize, lastDoc);
|
|
678
857
|
}
|
|
679
858
|
/**
|
|
680
|
-
*
|
|
681
|
-
* @param
|
|
682
|
-
* @
|
|
859
|
+
* Get a specific version of a template
|
|
860
|
+
* @param templateId - ID of the template
|
|
861
|
+
* @param versionNumber - Version number to retrieve
|
|
862
|
+
* @returns The template version or null if not found
|
|
683
863
|
*/
|
|
684
|
-
async
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
864
|
+
async getTemplateVersion(templateId, versionNumber) {
|
|
865
|
+
return this.apiService.getTemplateVersion(templateId, versionNumber);
|
|
866
|
+
}
|
|
867
|
+
/**
|
|
868
|
+
* Get all versions of a template
|
|
869
|
+
* @param templateId - ID of the template
|
|
870
|
+
* @returns Array of template versions
|
|
871
|
+
*/
|
|
872
|
+
async getTemplateVersions(templateId) {
|
|
873
|
+
return this.apiService.getTemplateOldVersions(templateId);
|
|
692
874
|
}
|
|
693
875
|
};
|
|
694
876
|
|
|
695
|
-
// src/backoffice/services/
|
|
877
|
+
// src/backoffice/services/product.service.ts
|
|
696
878
|
import {
|
|
697
|
-
addDoc as
|
|
698
|
-
collection as
|
|
699
|
-
doc as
|
|
700
|
-
getDoc as
|
|
701
|
-
getDocs as
|
|
702
|
-
query as
|
|
703
|
-
updateDoc as
|
|
704
|
-
where as
|
|
879
|
+
addDoc as addDoc3,
|
|
880
|
+
collection as collection6,
|
|
881
|
+
doc as doc6,
|
|
882
|
+
getDoc as getDoc6,
|
|
883
|
+
getDocs as getDocs6,
|
|
884
|
+
query as query6,
|
|
885
|
+
updateDoc as updateDoc6,
|
|
886
|
+
where as where6
|
|
705
887
|
} from "firebase/firestore";
|
|
706
|
-
|
|
888
|
+
|
|
889
|
+
// src/backoffice/types/product.types.ts
|
|
890
|
+
var PRODUCTS_COLLECTION = "products";
|
|
891
|
+
|
|
892
|
+
// src/backoffice/types/technology.types.ts
|
|
893
|
+
var TECHNOLOGIES_COLLECTION = "technologies";
|
|
894
|
+
|
|
895
|
+
// src/backoffice/services/product.service.ts
|
|
896
|
+
var ProductService = class extends BaseService {
|
|
707
897
|
/**
|
|
708
|
-
*
|
|
709
|
-
* @param
|
|
898
|
+
* Gets reference to products collection under a technology
|
|
899
|
+
* @param technologyId - ID of the technology
|
|
900
|
+
* @returns Firestore collection reference
|
|
710
901
|
*/
|
|
711
|
-
|
|
712
|
-
return
|
|
902
|
+
getProductsRef(technologyId) {
|
|
903
|
+
return collection6(
|
|
713
904
|
this.db,
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
905
|
+
TECHNOLOGIES_COLLECTION,
|
|
906
|
+
technologyId,
|
|
907
|
+
PRODUCTS_COLLECTION
|
|
717
908
|
);
|
|
718
909
|
}
|
|
719
910
|
/**
|
|
720
|
-
*
|
|
721
|
-
* @param categoryId - ID kategorije kojoj će pripadati nova podkategorija
|
|
722
|
-
* @param subcategory - Podaci za novu podkategoriju
|
|
723
|
-
* @returns Kreirana podkategorija sa generisanim ID-em
|
|
911
|
+
* Creates a new product under technology
|
|
724
912
|
*/
|
|
725
|
-
async create(
|
|
913
|
+
async create(technologyId, brandId, product) {
|
|
726
914
|
const now = /* @__PURE__ */ new Date();
|
|
727
|
-
const
|
|
728
|
-
...
|
|
729
|
-
|
|
915
|
+
const newProduct = {
|
|
916
|
+
...product,
|
|
917
|
+
brandId,
|
|
918
|
+
technologyId,
|
|
730
919
|
createdAt: now,
|
|
731
920
|
updatedAt: now,
|
|
732
921
|
isActive: true
|
|
733
922
|
};
|
|
734
|
-
const
|
|
735
|
-
this.
|
|
736
|
-
|
|
923
|
+
const productRef = await addDoc3(
|
|
924
|
+
this.getProductsRef(technologyId),
|
|
925
|
+
newProduct
|
|
737
926
|
);
|
|
738
|
-
return { id:
|
|
927
|
+
return { id: productRef.id, ...newProduct };
|
|
739
928
|
}
|
|
740
929
|
/**
|
|
741
|
-
*
|
|
742
|
-
* @param categoryId - ID kategorije čije podkategorije tražimo
|
|
743
|
-
* @returns Lista aktivnih podkategorija
|
|
930
|
+
* Gets all products for a technology
|
|
744
931
|
*/
|
|
745
|
-
async
|
|
746
|
-
const q =
|
|
747
|
-
this.
|
|
748
|
-
|
|
932
|
+
async getAllByTechnology(technologyId) {
|
|
933
|
+
const q = query6(
|
|
934
|
+
this.getProductsRef(technologyId),
|
|
935
|
+
where6("isActive", "==", true)
|
|
749
936
|
);
|
|
750
|
-
const snapshot = await
|
|
937
|
+
const snapshot = await getDocs6(q);
|
|
751
938
|
return snapshot.docs.map(
|
|
752
939
|
(doc10) => ({
|
|
753
940
|
id: doc10.id,
|
|
@@ -756,38 +943,56 @@ var SubcategoryService = class extends BaseService {
|
|
|
756
943
|
);
|
|
757
944
|
}
|
|
758
945
|
/**
|
|
759
|
-
*
|
|
760
|
-
* @param categoryId - ID kategorije kojoj pripada podkategorija
|
|
761
|
-
* @param subcategoryId - ID podkategorije koja se ažurira
|
|
762
|
-
* @param subcategory - Novi podaci za podkategoriju
|
|
763
|
-
* @returns Ažurirana podkategorija
|
|
946
|
+
* Gets all products for a brand by filtering through all technologies
|
|
764
947
|
*/
|
|
765
|
-
async
|
|
948
|
+
async getAllByBrand(brandId) {
|
|
949
|
+
const allTechnologiesRef = collection6(this.db, TECHNOLOGIES_COLLECTION);
|
|
950
|
+
const technologiesSnapshot = await getDocs6(allTechnologiesRef);
|
|
951
|
+
const products = [];
|
|
952
|
+
for (const techDoc of technologiesSnapshot.docs) {
|
|
953
|
+
const q = query6(
|
|
954
|
+
this.getProductsRef(techDoc.id),
|
|
955
|
+
where6("brandId", "==", brandId),
|
|
956
|
+
where6("isActive", "==", true)
|
|
957
|
+
);
|
|
958
|
+
const snapshot = await getDocs6(q);
|
|
959
|
+
products.push(
|
|
960
|
+
...snapshot.docs.map(
|
|
961
|
+
(doc10) => ({
|
|
962
|
+
id: doc10.id,
|
|
963
|
+
...doc10.data()
|
|
964
|
+
})
|
|
965
|
+
)
|
|
966
|
+
);
|
|
967
|
+
}
|
|
968
|
+
return products;
|
|
969
|
+
}
|
|
970
|
+
/**
|
|
971
|
+
* Updates a product
|
|
972
|
+
*/
|
|
973
|
+
async update(technologyId, productId, product) {
|
|
766
974
|
const updateData = {
|
|
767
|
-
...
|
|
975
|
+
...product,
|
|
768
976
|
updatedAt: /* @__PURE__ */ new Date()
|
|
769
977
|
};
|
|
770
|
-
const docRef =
|
|
771
|
-
await
|
|
772
|
-
return this.getById(
|
|
978
|
+
const docRef = doc6(this.getProductsRef(technologyId), productId);
|
|
979
|
+
await updateDoc6(docRef, updateData);
|
|
980
|
+
return this.getById(technologyId, productId);
|
|
773
981
|
}
|
|
774
982
|
/**
|
|
775
|
-
* Soft
|
|
776
|
-
* @param categoryId - ID kategorije kojoj pripada podkategorija
|
|
777
|
-
* @param subcategoryId - ID podkategorije koja se briše
|
|
983
|
+
* Soft deletes a product
|
|
778
984
|
*/
|
|
779
|
-
async delete(
|
|
780
|
-
await this.update(
|
|
985
|
+
async delete(technologyId, productId) {
|
|
986
|
+
await this.update(technologyId, productId, {
|
|
987
|
+
isActive: false
|
|
988
|
+
});
|
|
781
989
|
}
|
|
782
990
|
/**
|
|
783
|
-
*
|
|
784
|
-
* @param categoryId - ID kategorije kojoj pripada podkategorija
|
|
785
|
-
* @param subcategoryId - ID tražene podkategorije
|
|
786
|
-
* @returns Podkategorija ili null ako ne postoji
|
|
991
|
+
* Gets a product by ID
|
|
787
992
|
*/
|
|
788
|
-
async getById(
|
|
789
|
-
const docRef =
|
|
790
|
-
const docSnap = await
|
|
993
|
+
async getById(technologyId, productId) {
|
|
994
|
+
const docRef = doc6(this.getProductsRef(technologyId), productId);
|
|
995
|
+
const docSnap = await getDoc6(docRef);
|
|
791
996
|
if (!docSnap.exists()) return null;
|
|
792
997
|
return {
|
|
793
998
|
id: docSnap.id,
|
|
@@ -796,99 +1001,62 @@ var SubcategoryService = class extends BaseService {
|
|
|
796
1001
|
}
|
|
797
1002
|
};
|
|
798
1003
|
|
|
799
|
-
// src/backoffice/services/
|
|
1004
|
+
// src/backoffice/services/requirement.service.ts
|
|
800
1005
|
import {
|
|
801
|
-
addDoc as
|
|
802
|
-
collection as
|
|
803
|
-
doc as
|
|
804
|
-
getDoc as
|
|
805
|
-
getDocs as
|
|
806
|
-
query as
|
|
807
|
-
updateDoc as
|
|
808
|
-
where as
|
|
809
|
-
arrayUnion,
|
|
810
|
-
arrayRemove
|
|
1006
|
+
addDoc as addDoc4,
|
|
1007
|
+
collection as collection7,
|
|
1008
|
+
doc as doc7,
|
|
1009
|
+
getDoc as getDoc7,
|
|
1010
|
+
getDocs as getDocs7,
|
|
1011
|
+
query as query7,
|
|
1012
|
+
updateDoc as updateDoc7,
|
|
1013
|
+
where as where7
|
|
811
1014
|
} from "firebase/firestore";
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
async create(technology) {
|
|
829
|
-
const now = /* @__PURE__ */ new Date();
|
|
830
|
-
const newTechnology = {
|
|
831
|
-
...technology,
|
|
832
|
-
createdAt: now,
|
|
833
|
-
updatedAt: now,
|
|
834
|
-
isActive: true,
|
|
835
|
-
requirements: technology.requirements || {
|
|
836
|
-
pre: [],
|
|
837
|
-
post: []
|
|
838
|
-
},
|
|
839
|
-
blockingConditions: technology.blockingConditions || [],
|
|
840
|
-
contraindications: technology.contraindications || [],
|
|
841
|
-
benefits: technology.benefits || [],
|
|
842
|
-
certificationRequirement: technology.certificationRequirement || DEFAULT_CERTIFICATION_REQUIREMENT2
|
|
843
|
-
};
|
|
844
|
-
const docRef = await addDoc3(this.getTechnologiesRef(), newTechnology);
|
|
845
|
-
return { id: docRef.id, ...newTechnology };
|
|
846
|
-
}
|
|
1015
|
+
|
|
1016
|
+
// src/backoffice/types/requirement.types.ts
|
|
1017
|
+
var TimeUnit = /* @__PURE__ */ ((TimeUnit2) => {
|
|
1018
|
+
TimeUnit2["HOURS"] = "hours";
|
|
1019
|
+
TimeUnit2["DAYS"] = "days";
|
|
1020
|
+
return TimeUnit2;
|
|
1021
|
+
})(TimeUnit || {});
|
|
1022
|
+
var RequirementType = /* @__PURE__ */ ((RequirementType3) => {
|
|
1023
|
+
RequirementType3["PRE"] = "pre";
|
|
1024
|
+
RequirementType3["POST"] = "post";
|
|
1025
|
+
return RequirementType3;
|
|
1026
|
+
})(RequirementType || {});
|
|
1027
|
+
var REQUIREMENTS_COLLECTION = "backoffice_requirements";
|
|
1028
|
+
|
|
1029
|
+
// src/backoffice/services/requirement.service.ts
|
|
1030
|
+
var RequirementService = class extends BaseService {
|
|
847
1031
|
/**
|
|
848
|
-
*
|
|
849
|
-
* @returns Lista aktivnih tehnologija
|
|
1032
|
+
* Referenca na Firestore kolekciju zahteva
|
|
850
1033
|
*/
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
const snapshot = await getDocs3(q);
|
|
854
|
-
return snapshot.docs.map(
|
|
855
|
-
(doc10) => ({
|
|
856
|
-
id: doc10.id,
|
|
857
|
-
...doc10.data()
|
|
858
|
-
})
|
|
859
|
-
);
|
|
1034
|
+
get requirementsRef() {
|
|
1035
|
+
return collection7(this.db, REQUIREMENTS_COLLECTION);
|
|
860
1036
|
}
|
|
861
1037
|
/**
|
|
862
|
-
*
|
|
863
|
-
* @param
|
|
864
|
-
* @returns
|
|
1038
|
+
* Kreira novi globalni zahtev
|
|
1039
|
+
* @param requirement - Podaci za novi zahtev
|
|
1040
|
+
* @returns Kreirani zahtev sa generisanim ID-em
|
|
865
1041
|
*/
|
|
866
|
-
async
|
|
867
|
-
const
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
...doc10.data()
|
|
877
|
-
})
|
|
878
|
-
);
|
|
1042
|
+
async create(requirement) {
|
|
1043
|
+
const now = /* @__PURE__ */ new Date();
|
|
1044
|
+
const newRequirement = {
|
|
1045
|
+
...requirement,
|
|
1046
|
+
createdAt: now,
|
|
1047
|
+
updatedAt: now,
|
|
1048
|
+
isActive: true
|
|
1049
|
+
};
|
|
1050
|
+
const docRef = await addDoc4(this.requirementsRef, newRequirement);
|
|
1051
|
+
return { id: docRef.id, ...newRequirement };
|
|
879
1052
|
}
|
|
880
1053
|
/**
|
|
881
|
-
* Vraća sve aktivne
|
|
882
|
-
* @
|
|
883
|
-
* @returns Lista aktivnih tehnologija
|
|
1054
|
+
* Vraća sve aktivne zahteve
|
|
1055
|
+
* @returns Lista aktivnih zahteva
|
|
884
1056
|
*/
|
|
885
|
-
async
|
|
886
|
-
const q =
|
|
887
|
-
|
|
888
|
-
where3("isActive", "==", true),
|
|
889
|
-
where3("categoryId", "==", categoryId)
|
|
890
|
-
);
|
|
891
|
-
const snapshot = await getDocs3(q);
|
|
1057
|
+
async getAll() {
|
|
1058
|
+
const q = query7(this.requirementsRef, where7("isActive", "==", true));
|
|
1059
|
+
const snapshot = await getDocs7(q);
|
|
892
1060
|
return snapshot.docs.map(
|
|
893
1061
|
(doc10) => ({
|
|
894
1062
|
id: doc10.id,
|
|
@@ -897,17 +1065,17 @@ var TechnologyService = class extends BaseService {
|
|
|
897
1065
|
);
|
|
898
1066
|
}
|
|
899
1067
|
/**
|
|
900
|
-
* Vraća sve aktivne
|
|
901
|
-
* @param
|
|
902
|
-
* @returns Lista
|
|
1068
|
+
* Vraća sve aktivne zahteve određenog tipa
|
|
1069
|
+
* @param type - Tip zahteva (pre/post)
|
|
1070
|
+
* @returns Lista zahteva određenog tipa
|
|
903
1071
|
*/
|
|
904
|
-
async
|
|
905
|
-
const q =
|
|
906
|
-
this.
|
|
907
|
-
|
|
908
|
-
|
|
1072
|
+
async getAllByType(type) {
|
|
1073
|
+
const q = query7(
|
|
1074
|
+
this.requirementsRef,
|
|
1075
|
+
where7("type", "==", type),
|
|
1076
|
+
where7("isActive", "==", true)
|
|
909
1077
|
);
|
|
910
|
-
const snapshot = await
|
|
1078
|
+
const snapshot = await getDocs7(q);
|
|
911
1079
|
return snapshot.docs.map(
|
|
912
1080
|
(doc10) => ({
|
|
913
1081
|
id: doc10.id,
|
|
@@ -916,357 +1084,271 @@ var TechnologyService = class extends BaseService {
|
|
|
916
1084
|
);
|
|
917
1085
|
}
|
|
918
1086
|
/**
|
|
919
|
-
* Ažurira
|
|
920
|
-
* @param
|
|
921
|
-
* @param
|
|
922
|
-
* @returns
|
|
1087
|
+
* Ažurira postojeći zahtev
|
|
1088
|
+
* @param id - ID zahteva koji se ažurira
|
|
1089
|
+
* @param requirement - Novi podaci za zahtev
|
|
1090
|
+
* @returns Ažurirani zahtev
|
|
923
1091
|
*/
|
|
924
|
-
async update(
|
|
1092
|
+
async update(id, requirement) {
|
|
925
1093
|
const updateData = {
|
|
926
|
-
...
|
|
1094
|
+
...requirement,
|
|
927
1095
|
updatedAt: /* @__PURE__ */ new Date()
|
|
928
1096
|
};
|
|
929
|
-
const docRef =
|
|
930
|
-
await
|
|
931
|
-
return this.getById(
|
|
1097
|
+
const docRef = doc7(this.requirementsRef, id);
|
|
1098
|
+
await updateDoc7(docRef, updateData);
|
|
1099
|
+
return this.getById(id);
|
|
932
1100
|
}
|
|
933
1101
|
/**
|
|
934
|
-
* Soft delete
|
|
935
|
-
* @param
|
|
1102
|
+
* Soft delete zahteva (postavlja isActive na false)
|
|
1103
|
+
* @param id - ID zahteva koji se briše
|
|
936
1104
|
*/
|
|
937
|
-
async delete(
|
|
938
|
-
await this.update(
|
|
939
|
-
isActive: false
|
|
940
|
-
});
|
|
1105
|
+
async delete(id) {
|
|
1106
|
+
await this.update(id, { isActive: false });
|
|
941
1107
|
}
|
|
942
1108
|
/**
|
|
943
|
-
* Vraća
|
|
944
|
-
* @param
|
|
945
|
-
* @returns
|
|
1109
|
+
* Vraća zahtev po ID-u
|
|
1110
|
+
* @param id - ID traženog zahteva
|
|
1111
|
+
* @returns Zahtev ili null ako ne postoji
|
|
946
1112
|
*/
|
|
947
|
-
async getById(
|
|
948
|
-
const docRef =
|
|
949
|
-
const docSnap = await
|
|
1113
|
+
async getById(id) {
|
|
1114
|
+
const docRef = doc7(this.requirementsRef, id);
|
|
1115
|
+
const docSnap = await getDoc7(docRef);
|
|
950
1116
|
if (!docSnap.exists()) return null;
|
|
951
1117
|
return {
|
|
952
1118
|
id: docSnap.id,
|
|
953
1119
|
...docSnap.data()
|
|
954
1120
|
};
|
|
955
1121
|
}
|
|
1122
|
+
};
|
|
1123
|
+
|
|
1124
|
+
// src/backoffice/services/subcategory.service.ts
|
|
1125
|
+
import {
|
|
1126
|
+
addDoc as addDoc5,
|
|
1127
|
+
collection as collection8,
|
|
1128
|
+
doc as doc8,
|
|
1129
|
+
getDoc as getDoc8,
|
|
1130
|
+
getDocs as getDocs8,
|
|
1131
|
+
query as query8,
|
|
1132
|
+
updateDoc as updateDoc8,
|
|
1133
|
+
where as where8
|
|
1134
|
+
} from "firebase/firestore";
|
|
1135
|
+
|
|
1136
|
+
// src/backoffice/types/subcategory.types.ts
|
|
1137
|
+
var SUBCATEGORIES_COLLECTION = "subcategories";
|
|
1138
|
+
|
|
1139
|
+
// src/backoffice/services/subcategory.service.ts
|
|
1140
|
+
var SubcategoryService = class extends BaseService {
|
|
956
1141
|
/**
|
|
957
|
-
*
|
|
958
|
-
* @param
|
|
959
|
-
* @param requirement - Zahtev koji se dodaje
|
|
960
|
-
* @returns Ažurirana tehnologija sa novim zahtevom
|
|
961
|
-
*/
|
|
962
|
-
async addRequirement(technologyId, requirement) {
|
|
963
|
-
const docRef = doc3(this.getTechnologiesRef(), technologyId);
|
|
964
|
-
const requirementType = requirement.type === "pre" ? "requirements.pre" : "requirements.post";
|
|
965
|
-
await updateDoc3(docRef, {
|
|
966
|
-
[requirementType]: arrayUnion(requirement),
|
|
967
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
968
|
-
});
|
|
969
|
-
return this.getById(technologyId);
|
|
970
|
-
}
|
|
971
|
-
/**
|
|
972
|
-
* Uklanja zahtev iz tehnologije
|
|
973
|
-
* @param technologyId - ID tehnologije
|
|
974
|
-
* @param requirement - Zahtev koji se uklanja
|
|
975
|
-
* @returns Ažurirana tehnologija bez uklonjenog zahteva
|
|
976
|
-
*/
|
|
977
|
-
async removeRequirement(technologyId, requirement) {
|
|
978
|
-
const docRef = doc3(this.getTechnologiesRef(), technologyId);
|
|
979
|
-
const requirementType = requirement.type === "pre" ? "requirements.pre" : "requirements.post";
|
|
980
|
-
await updateDoc3(docRef, {
|
|
981
|
-
[requirementType]: arrayRemove(requirement),
|
|
982
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
983
|
-
});
|
|
984
|
-
return this.getById(technologyId);
|
|
985
|
-
}
|
|
986
|
-
/**
|
|
987
|
-
* Vraća sve zahteve za tehnologiju
|
|
988
|
-
* @param technologyId - ID tehnologije
|
|
989
|
-
* @param type - Opcioni filter za tip zahteva (pre/post)
|
|
990
|
-
* @returns Lista zahteva
|
|
991
|
-
*/
|
|
992
|
-
async getRequirements(technologyId, type) {
|
|
993
|
-
const technology = await this.getById(technologyId);
|
|
994
|
-
if (!technology || !technology.requirements) return [];
|
|
995
|
-
if (type) {
|
|
996
|
-
return technology.requirements[type];
|
|
997
|
-
}
|
|
998
|
-
return [...technology.requirements.pre, ...technology.requirements.post];
|
|
999
|
-
}
|
|
1000
|
-
/**
|
|
1001
|
-
* Ažurira postojeći zahtev
|
|
1002
|
-
* @param technologyId - ID tehnologije
|
|
1003
|
-
* @param oldRequirement - Stari zahtev koji se menja
|
|
1004
|
-
* @param newRequirement - Novi zahtev koji zamenjuje stari
|
|
1005
|
-
* @returns Ažurirana tehnologija
|
|
1006
|
-
*/
|
|
1007
|
-
async updateRequirement(technologyId, oldRequirement, newRequirement) {
|
|
1008
|
-
await this.removeRequirement(technologyId, oldRequirement);
|
|
1009
|
-
return this.addRequirement(technologyId, newRequirement);
|
|
1010
|
-
}
|
|
1011
|
-
/**
|
|
1012
|
-
* Dodaje blokirajući uslov tehnologiji
|
|
1013
|
-
* @param technologyId - ID tehnologije
|
|
1014
|
-
* @param condition - Blokirajući uslov koji se dodaje
|
|
1015
|
-
* @returns Ažurirana tehnologija
|
|
1016
|
-
*/
|
|
1017
|
-
async addBlockingCondition(technologyId, condition) {
|
|
1018
|
-
const docRef = doc3(this.getTechnologiesRef(), technologyId);
|
|
1019
|
-
await updateDoc3(docRef, {
|
|
1020
|
-
blockingConditions: arrayUnion(condition),
|
|
1021
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
1022
|
-
});
|
|
1023
|
-
return this.getById(technologyId);
|
|
1024
|
-
}
|
|
1025
|
-
/**
|
|
1026
|
-
* Uklanja blokirajući uslov iz tehnologije
|
|
1027
|
-
* @param technologyId - ID tehnologije
|
|
1028
|
-
* @param condition - Blokirajući uslov koji se uklanja
|
|
1029
|
-
* @returns Ažurirana tehnologija
|
|
1030
|
-
*/
|
|
1031
|
-
async removeBlockingCondition(technologyId, condition) {
|
|
1032
|
-
const docRef = doc3(this.getTechnologiesRef(), technologyId);
|
|
1033
|
-
await updateDoc3(docRef, {
|
|
1034
|
-
blockingConditions: arrayRemove(condition),
|
|
1035
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
1036
|
-
});
|
|
1037
|
-
return this.getById(technologyId);
|
|
1038
|
-
}
|
|
1039
|
-
/**
|
|
1040
|
-
* Dodaje kontraindikaciju tehnologiji
|
|
1041
|
-
* @param technologyId - ID tehnologije
|
|
1042
|
-
* @param contraindication - Kontraindikacija koja se dodaje
|
|
1043
|
-
* @returns Ažurirana tehnologija
|
|
1044
|
-
*/
|
|
1045
|
-
async addContraindication(technologyId, contraindication) {
|
|
1046
|
-
const docRef = doc3(this.getTechnologiesRef(), technologyId);
|
|
1047
|
-
await updateDoc3(docRef, {
|
|
1048
|
-
contraindications: arrayUnion(contraindication),
|
|
1049
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
1050
|
-
});
|
|
1051
|
-
return this.getById(technologyId);
|
|
1052
|
-
}
|
|
1053
|
-
/**
|
|
1054
|
-
* Uklanja kontraindikaciju iz tehnologije
|
|
1055
|
-
* @param technologyId - ID tehnologije
|
|
1056
|
-
* @param contraindication - Kontraindikacija koja se uklanja
|
|
1057
|
-
* @returns Ažurirana tehnologija
|
|
1058
|
-
*/
|
|
1059
|
-
async removeContraindication(technologyId, contraindication) {
|
|
1060
|
-
const docRef = doc3(this.getTechnologiesRef(), technologyId);
|
|
1061
|
-
await updateDoc3(docRef, {
|
|
1062
|
-
contraindications: arrayRemove(contraindication),
|
|
1063
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
1064
|
-
});
|
|
1065
|
-
return this.getById(technologyId);
|
|
1066
|
-
}
|
|
1067
|
-
/**
|
|
1068
|
-
* Dodaje benefit tehnologiji
|
|
1069
|
-
* @param technologyId - ID tehnologije
|
|
1070
|
-
* @param benefit - Benefit koji se dodaje
|
|
1071
|
-
* @returns Ažurirana tehnologija
|
|
1072
|
-
*/
|
|
1073
|
-
async addBenefit(technologyId, benefit) {
|
|
1074
|
-
const docRef = doc3(this.getTechnologiesRef(), technologyId);
|
|
1075
|
-
await updateDoc3(docRef, {
|
|
1076
|
-
benefits: arrayUnion(benefit),
|
|
1077
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
1078
|
-
});
|
|
1079
|
-
return this.getById(technologyId);
|
|
1080
|
-
}
|
|
1081
|
-
/**
|
|
1082
|
-
* Uklanja benefit iz tehnologije
|
|
1083
|
-
* @param technologyId - ID tehnologije
|
|
1084
|
-
* @param benefit - Benefit koji se uklanja
|
|
1085
|
-
* @returns Ažurirana tehnologija
|
|
1086
|
-
*/
|
|
1087
|
-
async removeBenefit(technologyId, benefit) {
|
|
1088
|
-
const docRef = doc3(this.getTechnologiesRef(), technologyId);
|
|
1089
|
-
await updateDoc3(docRef, {
|
|
1090
|
-
benefits: arrayRemove(benefit),
|
|
1091
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
1092
|
-
});
|
|
1093
|
-
return this.getById(technologyId);
|
|
1094
|
-
}
|
|
1095
|
-
/**
|
|
1096
|
-
* Vraća sve blokirajuće uslove za tehnologiju
|
|
1097
|
-
* @param technologyId - ID tehnologije
|
|
1098
|
-
* @returns Lista blokirajućih uslova
|
|
1099
|
-
*/
|
|
1100
|
-
async getBlockingConditions(technologyId) {
|
|
1101
|
-
const technology = await this.getById(technologyId);
|
|
1102
|
-
return (technology == null ? void 0 : technology.blockingConditions) || [];
|
|
1103
|
-
}
|
|
1104
|
-
/**
|
|
1105
|
-
* Vraća sve kontraindikacije za tehnologiju
|
|
1106
|
-
* @param technologyId - ID tehnologije
|
|
1107
|
-
* @returns Lista kontraindikacija
|
|
1142
|
+
* Vraća referencu na Firestore kolekciju podkategorija za određenu kategoriju
|
|
1143
|
+
* @param categoryId - ID roditeljske kategorije
|
|
1108
1144
|
*/
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1145
|
+
getSubcategoriesRef(categoryId) {
|
|
1146
|
+
return collection8(
|
|
1147
|
+
this.db,
|
|
1148
|
+
CATEGORIES_COLLECTION,
|
|
1149
|
+
categoryId,
|
|
1150
|
+
SUBCATEGORIES_COLLECTION
|
|
1151
|
+
);
|
|
1112
1152
|
}
|
|
1113
1153
|
/**
|
|
1114
|
-
*
|
|
1115
|
-
* @param
|
|
1116
|
-
* @
|
|
1154
|
+
* Kreira novu podkategoriju u okviru kategorije
|
|
1155
|
+
* @param categoryId - ID kategorije kojoj će pripadati nova podkategorija
|
|
1156
|
+
* @param subcategory - Podaci za novu podkategoriju
|
|
1157
|
+
* @returns Kreirana podkategorija sa generisanim ID-em
|
|
1117
1158
|
*/
|
|
1118
|
-
async
|
|
1119
|
-
const
|
|
1120
|
-
|
|
1159
|
+
async create(categoryId, subcategory) {
|
|
1160
|
+
const now = /* @__PURE__ */ new Date();
|
|
1161
|
+
const newSubcategory = {
|
|
1162
|
+
...subcategory,
|
|
1163
|
+
categoryId,
|
|
1164
|
+
createdAt: now,
|
|
1165
|
+
updatedAt: now,
|
|
1166
|
+
isActive: true
|
|
1167
|
+
};
|
|
1168
|
+
const docRef = await addDoc5(
|
|
1169
|
+
this.getSubcategoriesRef(categoryId),
|
|
1170
|
+
newSubcategory
|
|
1171
|
+
);
|
|
1172
|
+
return { id: docRef.id, ...newSubcategory };
|
|
1121
1173
|
}
|
|
1122
1174
|
/**
|
|
1123
|
-
*
|
|
1124
|
-
* @param
|
|
1125
|
-
* @
|
|
1126
|
-
* @returns Ažurirana tehnologija
|
|
1175
|
+
* Vraća sve aktivne podkategorije za određenu kategoriju
|
|
1176
|
+
* @param categoryId - ID kategorije čije podkategorije tražimo
|
|
1177
|
+
* @returns Lista aktivnih podkategorija
|
|
1127
1178
|
*/
|
|
1128
|
-
async
|
|
1129
|
-
const
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
return
|
|
1179
|
+
async getAllByCategoryId(categoryId) {
|
|
1180
|
+
const q = query8(
|
|
1181
|
+
this.getSubcategoriesRef(categoryId),
|
|
1182
|
+
where8("isActive", "==", true)
|
|
1183
|
+
);
|
|
1184
|
+
const snapshot = await getDocs8(q);
|
|
1185
|
+
return snapshot.docs.map(
|
|
1186
|
+
(doc10) => ({
|
|
1187
|
+
id: doc10.id,
|
|
1188
|
+
...doc10.data()
|
|
1189
|
+
})
|
|
1190
|
+
);
|
|
1135
1191
|
}
|
|
1136
1192
|
/**
|
|
1137
|
-
*
|
|
1138
|
-
* @param
|
|
1139
|
-
* @
|
|
1193
|
+
* Ažurira postojeću podkategoriju
|
|
1194
|
+
* @param categoryId - ID kategorije kojoj pripada podkategorija
|
|
1195
|
+
* @param subcategoryId - ID podkategorije koja se ažurira
|
|
1196
|
+
* @param subcategory - Novi podaci za podkategoriju
|
|
1197
|
+
* @returns Ažurirana podkategorija
|
|
1140
1198
|
*/
|
|
1141
|
-
async
|
|
1142
|
-
const
|
|
1143
|
-
|
|
1199
|
+
async update(categoryId, subcategoryId, subcategory) {
|
|
1200
|
+
const updateData = {
|
|
1201
|
+
...subcategory,
|
|
1202
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
1203
|
+
};
|
|
1204
|
+
const docRef = doc8(this.getSubcategoriesRef(categoryId), subcategoryId);
|
|
1205
|
+
await updateDoc8(docRef, updateData);
|
|
1206
|
+
return this.getById(categoryId, subcategoryId);
|
|
1144
1207
|
}
|
|
1145
1208
|
/**
|
|
1146
|
-
*
|
|
1147
|
-
*
|
|
1148
|
-
* @param
|
|
1149
|
-
* @param practitionerCertification - Sertifikacija zdravstvenog radnika
|
|
1150
|
-
* @returns true ako zdravstveni radnik ima odgovarajuću sertifikaciju, false ako nema
|
|
1151
|
-
*
|
|
1152
|
-
* @example
|
|
1153
|
-
* const isValid = technologyService.validateCertification(
|
|
1154
|
-
* {
|
|
1155
|
-
* minimumLevel: CertificationLevel.DOCTOR,
|
|
1156
|
-
* requiredSpecialties: [CertificationSpecialty.INJECTABLES]
|
|
1157
|
-
* },
|
|
1158
|
-
* {
|
|
1159
|
-
* level: CertificationLevel.SPECIALIST,
|
|
1160
|
-
* specialties: [CertificationSpecialty.INJECTABLES, CertificationSpecialty.LASER]
|
|
1161
|
-
* }
|
|
1162
|
-
* );
|
|
1209
|
+
* Soft delete podkategorije (postavlja isActive na false)
|
|
1210
|
+
* @param categoryId - ID kategorije kojoj pripada podkategorija
|
|
1211
|
+
* @param subcategoryId - ID podkategorije koja se briše
|
|
1163
1212
|
*/
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
practitionerCertification.level
|
|
1167
|
-
);
|
|
1168
|
-
const requiredLevel = Object.values(CertificationLevel).indexOf(
|
|
1169
|
-
requiredCertification.minimumLevel
|
|
1170
|
-
);
|
|
1171
|
-
if (doctorLevel < requiredLevel) return false;
|
|
1172
|
-
const requiredSpecialties = requiredCertification.requiredSpecialties || [];
|
|
1173
|
-
if (requiredSpecialties.length > 0) {
|
|
1174
|
-
const doctorSpecialties = practitionerCertification.specialties;
|
|
1175
|
-
const hasAllRequiredSpecialties = requiredSpecialties.every(
|
|
1176
|
-
(requiredSpecialty) => doctorSpecialties.includes(requiredSpecialty)
|
|
1177
|
-
);
|
|
1178
|
-
if (!hasAllRequiredSpecialties) return false;
|
|
1179
|
-
}
|
|
1180
|
-
return true;
|
|
1213
|
+
async delete(categoryId, subcategoryId) {
|
|
1214
|
+
await this.update(categoryId, subcategoryId, { isActive: false });
|
|
1181
1215
|
}
|
|
1182
1216
|
/**
|
|
1183
|
-
* Vraća
|
|
1184
|
-
*
|
|
1185
|
-
*
|
|
1186
|
-
* @
|
|
1187
|
-
* @returns Objekat koji sadrži:
|
|
1188
|
-
* - technologies: Lista tehnologija koje zdravstveni radnik može da izvodi
|
|
1189
|
-
* - families: Lista familija procedura koje zdravstveni radnik može da izvodi
|
|
1190
|
-
* - categories: Lista ID-eva kategorija koje zdravstveni radnik može da izvodi
|
|
1191
|
-
* - subcategories: Lista ID-eva podkategorija koje zdravstveni radnik može da izvodi
|
|
1192
|
-
*
|
|
1193
|
-
* @example
|
|
1194
|
-
* const practitioner = {
|
|
1195
|
-
* certification: {
|
|
1196
|
-
* level: CertificationLevel.DOCTOR,
|
|
1197
|
-
* specialties: [CertificationSpecialty.INJECTABLES]
|
|
1198
|
-
* }
|
|
1199
|
-
* };
|
|
1200
|
-
* const allowedTechnologies = await technologyService.getAllowedTechnologies(practitioner);
|
|
1201
|
-
* console.log(allowedTechnologies.families); // [ProcedureFamily.AESTHETICS]
|
|
1202
|
-
* console.log(allowedTechnologies.categories); // ["category1", "category2"]
|
|
1203
|
-
* console.log(allowedTechnologies.subcategories); // ["subcategory1", "subcategory2"]
|
|
1217
|
+
* Vraća podkategoriju po ID-u
|
|
1218
|
+
* @param categoryId - ID kategorije kojoj pripada podkategorija
|
|
1219
|
+
* @param subcategoryId - ID tražene podkategorije
|
|
1220
|
+
* @returns Podkategorija ili null ako ne postoji
|
|
1204
1221
|
*/
|
|
1205
|
-
async
|
|
1206
|
-
const
|
|
1207
|
-
const
|
|
1208
|
-
|
|
1209
|
-
technology.certificationRequirement,
|
|
1210
|
-
practitioner.certification
|
|
1211
|
-
)
|
|
1212
|
-
);
|
|
1213
|
-
const families = [...new Set(allowedTechnologies.map((t) => t.family))];
|
|
1214
|
-
const categories = [
|
|
1215
|
-
...new Set(allowedTechnologies.map((t) => t.categoryId))
|
|
1216
|
-
];
|
|
1217
|
-
const subcategories = [
|
|
1218
|
-
...new Set(allowedTechnologies.map((t) => t.subcategoryId))
|
|
1219
|
-
];
|
|
1222
|
+
async getById(categoryId, subcategoryId) {
|
|
1223
|
+
const docRef = doc8(this.getSubcategoriesRef(categoryId), subcategoryId);
|
|
1224
|
+
const docSnap = await getDoc8(docRef);
|
|
1225
|
+
if (!docSnap.exists()) return null;
|
|
1220
1226
|
return {
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
categories,
|
|
1224
|
-
subcategories
|
|
1227
|
+
id: docSnap.id,
|
|
1228
|
+
...docSnap.data()
|
|
1225
1229
|
};
|
|
1226
1230
|
}
|
|
1227
1231
|
};
|
|
1228
1232
|
|
|
1229
|
-
// src/backoffice/services/
|
|
1233
|
+
// src/backoffice/services/technology.service.ts
|
|
1230
1234
|
import {
|
|
1231
|
-
addDoc as
|
|
1232
|
-
collection as
|
|
1233
|
-
doc as
|
|
1234
|
-
getDoc as
|
|
1235
|
-
getDocs as
|
|
1236
|
-
query as
|
|
1237
|
-
updateDoc as
|
|
1238
|
-
where as
|
|
1235
|
+
addDoc as addDoc6,
|
|
1236
|
+
collection as collection9,
|
|
1237
|
+
doc as doc9,
|
|
1238
|
+
getDoc as getDoc9,
|
|
1239
|
+
getDocs as getDocs9,
|
|
1240
|
+
query as query9,
|
|
1241
|
+
updateDoc as updateDoc9,
|
|
1242
|
+
where as where9,
|
|
1243
|
+
arrayUnion,
|
|
1244
|
+
arrayRemove
|
|
1239
1245
|
} from "firebase/firestore";
|
|
1240
|
-
|
|
1246
|
+
|
|
1247
|
+
// src/backoffice/types/static/certification.types.ts
|
|
1248
|
+
var CertificationLevel = /* @__PURE__ */ ((CertificationLevel2) => {
|
|
1249
|
+
CertificationLevel2["AESTHETICIAN"] = "aesthetician";
|
|
1250
|
+
CertificationLevel2["NURSE_ASSISTANT"] = "nurse_assistant";
|
|
1251
|
+
CertificationLevel2["NURSE"] = "nurse";
|
|
1252
|
+
CertificationLevel2["NURSE_PRACTITIONER"] = "nurse_practitioner";
|
|
1253
|
+
CertificationLevel2["PHYSICIAN_ASSISTANT"] = "physician_assistant";
|
|
1254
|
+
CertificationLevel2["DOCTOR"] = "doctor";
|
|
1255
|
+
CertificationLevel2["SPECIALIST"] = "specialist";
|
|
1256
|
+
CertificationLevel2["PLASTIC_SURGEON"] = "plastic_surgeon";
|
|
1257
|
+
return CertificationLevel2;
|
|
1258
|
+
})(CertificationLevel || {});
|
|
1259
|
+
var CertificationSpecialty = /* @__PURE__ */ ((CertificationSpecialty3) => {
|
|
1260
|
+
CertificationSpecialty3["LASER"] = "laser";
|
|
1261
|
+
CertificationSpecialty3["INJECTABLES"] = "injectables";
|
|
1262
|
+
CertificationSpecialty3["CHEMICAL_PEELS"] = "chemical_peels";
|
|
1263
|
+
CertificationSpecialty3["MICRODERMABRASION"] = "microdermabrasion";
|
|
1264
|
+
CertificationSpecialty3["BODY_CONTOURING"] = "body_contouring";
|
|
1265
|
+
CertificationSpecialty3["SKIN_CARE"] = "skin_care";
|
|
1266
|
+
CertificationSpecialty3["WOUND_CARE"] = "wound_care";
|
|
1267
|
+
CertificationSpecialty3["ANESTHESIA"] = "anesthesia";
|
|
1268
|
+
return CertificationSpecialty3;
|
|
1269
|
+
})(CertificationSpecialty || {});
|
|
1270
|
+
|
|
1271
|
+
// src/backoffice/services/technology.service.ts
|
|
1272
|
+
var DEFAULT_CERTIFICATION_REQUIREMENT = {
|
|
1273
|
+
minimumLevel: "aesthetician" /* AESTHETICIAN */,
|
|
1274
|
+
requiredSpecialties: []
|
|
1275
|
+
};
|
|
1276
|
+
var TechnologyService = class extends BaseService {
|
|
1241
1277
|
/**
|
|
1242
|
-
*
|
|
1278
|
+
* Vraća referencu na Firestore kolekciju tehnologija
|
|
1243
1279
|
*/
|
|
1244
|
-
|
|
1245
|
-
return
|
|
1280
|
+
getTechnologiesRef() {
|
|
1281
|
+
return collection9(this.db, TECHNOLOGIES_COLLECTION);
|
|
1246
1282
|
}
|
|
1247
1283
|
/**
|
|
1248
|
-
* Kreira
|
|
1249
|
-
* @param
|
|
1250
|
-
* @returns
|
|
1284
|
+
* Kreira novu tehnologiju
|
|
1285
|
+
* @param technology - Podaci za novu tehnologiju
|
|
1286
|
+
* @returns Kreirana tehnologija sa generisanim ID-em
|
|
1251
1287
|
*/
|
|
1252
|
-
async create(
|
|
1288
|
+
async create(technology) {
|
|
1253
1289
|
const now = /* @__PURE__ */ new Date();
|
|
1254
|
-
const
|
|
1255
|
-
...
|
|
1290
|
+
const newTechnology = {
|
|
1291
|
+
...technology,
|
|
1256
1292
|
createdAt: now,
|
|
1257
1293
|
updatedAt: now,
|
|
1258
|
-
isActive: true
|
|
1294
|
+
isActive: true,
|
|
1295
|
+
requirements: technology.requirements || {
|
|
1296
|
+
pre: [],
|
|
1297
|
+
post: []
|
|
1298
|
+
},
|
|
1299
|
+
blockingConditions: technology.blockingConditions || [],
|
|
1300
|
+
contraindications: technology.contraindications || [],
|
|
1301
|
+
benefits: technology.benefits || [],
|
|
1302
|
+
certificationRequirement: technology.certificationRequirement || DEFAULT_CERTIFICATION_REQUIREMENT
|
|
1259
1303
|
};
|
|
1260
|
-
const docRef = await
|
|
1261
|
-
return { id: docRef.id, ...
|
|
1304
|
+
const docRef = await addDoc6(this.getTechnologiesRef(), newTechnology);
|
|
1305
|
+
return { id: docRef.id, ...newTechnology };
|
|
1262
1306
|
}
|
|
1263
1307
|
/**
|
|
1264
|
-
* Vraća sve aktivne
|
|
1265
|
-
* @returns Lista aktivnih
|
|
1308
|
+
* Vraća sve aktivne tehnologije
|
|
1309
|
+
* @returns Lista aktivnih tehnologija
|
|
1310
|
+
*/
|
|
1311
|
+
async getAll() {
|
|
1312
|
+
const q = query9(this.getTechnologiesRef(), where9("isActive", "==", true));
|
|
1313
|
+
const snapshot = await getDocs9(q);
|
|
1314
|
+
return snapshot.docs.map(
|
|
1315
|
+
(doc10) => ({
|
|
1316
|
+
id: doc10.id,
|
|
1317
|
+
...doc10.data()
|
|
1318
|
+
})
|
|
1319
|
+
);
|
|
1320
|
+
}
|
|
1321
|
+
/**
|
|
1322
|
+
* Vraća sve aktivne tehnologije za određenu familiju
|
|
1323
|
+
* @param family - Familija procedura
|
|
1324
|
+
* @returns Lista aktivnih tehnologija
|
|
1325
|
+
*/
|
|
1326
|
+
async getAllByFamily(family) {
|
|
1327
|
+
const q = query9(
|
|
1328
|
+
this.getTechnologiesRef(),
|
|
1329
|
+
where9("isActive", "==", true),
|
|
1330
|
+
where9("family", "==", family)
|
|
1331
|
+
);
|
|
1332
|
+
const snapshot = await getDocs9(q);
|
|
1333
|
+
return snapshot.docs.map(
|
|
1334
|
+
(doc10) => ({
|
|
1335
|
+
id: doc10.id,
|
|
1336
|
+
...doc10.data()
|
|
1337
|
+
})
|
|
1338
|
+
);
|
|
1339
|
+
}
|
|
1340
|
+
/**
|
|
1341
|
+
* Vraća sve aktivne tehnologije za određenu kategoriju
|
|
1342
|
+
* @param categoryId - ID kategorije
|
|
1343
|
+
* @returns Lista aktivnih tehnologija
|
|
1266
1344
|
*/
|
|
1267
|
-
async
|
|
1268
|
-
const q =
|
|
1269
|
-
|
|
1345
|
+
async getAllByCategoryId(categoryId) {
|
|
1346
|
+
const q = query9(
|
|
1347
|
+
this.getTechnologiesRef(),
|
|
1348
|
+
where9("isActive", "==", true),
|
|
1349
|
+
where9("categoryId", "==", categoryId)
|
|
1350
|
+
);
|
|
1351
|
+
const snapshot = await getDocs9(q);
|
|
1270
1352
|
return snapshot.docs.map(
|
|
1271
1353
|
(doc10) => ({
|
|
1272
1354
|
id: doc10.id,
|
|
@@ -1275,17 +1357,17 @@ var RequirementService = class extends BaseService {
|
|
|
1275
1357
|
);
|
|
1276
1358
|
}
|
|
1277
1359
|
/**
|
|
1278
|
-
* Vraća sve aktivne
|
|
1279
|
-
* @param
|
|
1280
|
-
* @returns Lista
|
|
1360
|
+
* Vraća sve aktivne tehnologije za određenu podkategoriju
|
|
1361
|
+
* @param subcategoryId - ID podkategorije
|
|
1362
|
+
* @returns Lista aktivnih tehnologija
|
|
1281
1363
|
*/
|
|
1282
|
-
async
|
|
1283
|
-
const q =
|
|
1284
|
-
this.
|
|
1285
|
-
|
|
1286
|
-
|
|
1364
|
+
async getAllBySubcategoryId(subcategoryId) {
|
|
1365
|
+
const q = query9(
|
|
1366
|
+
this.getTechnologiesRef(),
|
|
1367
|
+
where9("isActive", "==", true),
|
|
1368
|
+
where9("subcategoryId", "==", subcategoryId)
|
|
1287
1369
|
);
|
|
1288
|
-
const snapshot = await
|
|
1370
|
+
const snapshot = await getDocs9(q);
|
|
1289
1371
|
return snapshot.docs.map(
|
|
1290
1372
|
(doc10) => ({
|
|
1291
1373
|
id: doc10.id,
|
|
@@ -1294,663 +1376,591 @@ var RequirementService = class extends BaseService {
|
|
|
1294
1376
|
);
|
|
1295
1377
|
}
|
|
1296
1378
|
/**
|
|
1297
|
-
* Ažurira
|
|
1298
|
-
* @param
|
|
1299
|
-
* @param
|
|
1300
|
-
* @returns
|
|
1379
|
+
* Ažurira postojeću tehnologiju
|
|
1380
|
+
* @param technologyId - ID tehnologije
|
|
1381
|
+
* @param technology - Novi podaci za tehnologiju
|
|
1382
|
+
* @returns Ažurirana tehnologija
|
|
1301
1383
|
*/
|
|
1302
|
-
async update(
|
|
1384
|
+
async update(technologyId, technology) {
|
|
1303
1385
|
const updateData = {
|
|
1304
|
-
...
|
|
1386
|
+
...technology,
|
|
1305
1387
|
updatedAt: /* @__PURE__ */ new Date()
|
|
1306
1388
|
};
|
|
1307
|
-
const docRef =
|
|
1308
|
-
await
|
|
1309
|
-
return this.getById(
|
|
1389
|
+
const docRef = doc9(this.getTechnologiesRef(), technologyId);
|
|
1390
|
+
await updateDoc9(docRef, updateData);
|
|
1391
|
+
return this.getById(technologyId);
|
|
1310
1392
|
}
|
|
1311
1393
|
/**
|
|
1312
|
-
* Soft delete
|
|
1313
|
-
* @param
|
|
1394
|
+
* Soft delete tehnologije (postavlja isActive na false)
|
|
1395
|
+
* @param technologyId - ID tehnologije koja se briše
|
|
1314
1396
|
*/
|
|
1315
|
-
async delete(
|
|
1316
|
-
await this.update(
|
|
1397
|
+
async delete(technologyId) {
|
|
1398
|
+
await this.update(technologyId, {
|
|
1399
|
+
isActive: false
|
|
1400
|
+
});
|
|
1317
1401
|
}
|
|
1318
1402
|
/**
|
|
1319
|
-
* Vraća
|
|
1320
|
-
* @param
|
|
1321
|
-
* @returns
|
|
1403
|
+
* Vraća tehnologiju po ID-u
|
|
1404
|
+
* @param technologyId - ID tražene tehnologije
|
|
1405
|
+
* @returns Tehnologija ili null ako ne postoji
|
|
1322
1406
|
*/
|
|
1323
|
-
async getById(
|
|
1324
|
-
const docRef =
|
|
1325
|
-
const docSnap = await
|
|
1407
|
+
async getById(technologyId) {
|
|
1408
|
+
const docRef = doc9(this.getTechnologiesRef(), technologyId);
|
|
1409
|
+
const docSnap = await getDoc9(docRef);
|
|
1326
1410
|
if (!docSnap.exists()) return null;
|
|
1327
1411
|
return {
|
|
1328
1412
|
id: docSnap.id,
|
|
1329
1413
|
...docSnap.data()
|
|
1330
1414
|
};
|
|
1331
1415
|
}
|
|
1332
|
-
};
|
|
1333
|
-
|
|
1334
|
-
// src/backoffice/services/brand.service.ts
|
|
1335
|
-
import {
|
|
1336
|
-
addDoc as addDoc5,
|
|
1337
|
-
collection as collection5,
|
|
1338
|
-
doc as doc5,
|
|
1339
|
-
getDoc as getDoc5,
|
|
1340
|
-
getDocs as getDocs5,
|
|
1341
|
-
query as query5,
|
|
1342
|
-
updateDoc as updateDoc5,
|
|
1343
|
-
where as where5
|
|
1344
|
-
} from "firebase/firestore";
|
|
1345
|
-
var BrandService = class extends BaseService {
|
|
1346
1416
|
/**
|
|
1347
|
-
*
|
|
1417
|
+
* Dodaje novi zahtev tehnologiji
|
|
1418
|
+
* @param technologyId - ID tehnologije
|
|
1419
|
+
* @param requirement - Zahtev koji se dodaje
|
|
1420
|
+
* @returns Ažurirana tehnologija sa novim zahtevom
|
|
1348
1421
|
*/
|
|
1349
|
-
|
|
1350
|
-
|
|
1422
|
+
async addRequirement(technologyId, requirement) {
|
|
1423
|
+
const docRef = doc9(this.getTechnologiesRef(), technologyId);
|
|
1424
|
+
const requirementType = requirement.type === "pre" ? "requirements.pre" : "requirements.post";
|
|
1425
|
+
await updateDoc9(docRef, {
|
|
1426
|
+
[requirementType]: arrayUnion(requirement),
|
|
1427
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
1428
|
+
});
|
|
1429
|
+
return this.getById(technologyId);
|
|
1351
1430
|
}
|
|
1352
1431
|
/**
|
|
1353
|
-
*
|
|
1432
|
+
* Uklanja zahtev iz tehnologije
|
|
1433
|
+
* @param technologyId - ID tehnologije
|
|
1434
|
+
* @param requirement - Zahtev koji se uklanja
|
|
1435
|
+
* @returns Ažurirana tehnologija bez uklonjenog zahteva
|
|
1354
1436
|
*/
|
|
1355
|
-
async
|
|
1356
|
-
const
|
|
1357
|
-
const
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
updatedAt:
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
const docRef = await addDoc5(this.getBrandsRef(), newBrand);
|
|
1364
|
-
return { id: docRef.id, ...newBrand };
|
|
1437
|
+
async removeRequirement(technologyId, requirement) {
|
|
1438
|
+
const docRef = doc9(this.getTechnologiesRef(), technologyId);
|
|
1439
|
+
const requirementType = requirement.type === "pre" ? "requirements.pre" : "requirements.post";
|
|
1440
|
+
await updateDoc9(docRef, {
|
|
1441
|
+
[requirementType]: arrayRemove(requirement),
|
|
1442
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
1443
|
+
});
|
|
1444
|
+
return this.getById(technologyId);
|
|
1365
1445
|
}
|
|
1366
1446
|
/**
|
|
1367
|
-
*
|
|
1447
|
+
* Vraća sve zahteve za tehnologiju
|
|
1448
|
+
* @param technologyId - ID tehnologije
|
|
1449
|
+
* @param type - Opcioni filter za tip zahteva (pre/post)
|
|
1450
|
+
* @returns Lista zahteva
|
|
1368
1451
|
*/
|
|
1369
|
-
async
|
|
1370
|
-
const
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
})
|
|
1377
|
-
);
|
|
1452
|
+
async getRequirements(technologyId, type) {
|
|
1453
|
+
const technology = await this.getById(technologyId);
|
|
1454
|
+
if (!technology || !technology.requirements) return [];
|
|
1455
|
+
if (type) {
|
|
1456
|
+
return technology.requirements[type];
|
|
1457
|
+
}
|
|
1458
|
+
return [...technology.requirements.pre, ...technology.requirements.post];
|
|
1378
1459
|
}
|
|
1379
1460
|
/**
|
|
1380
|
-
*
|
|
1461
|
+
* Ažurira postojeći zahtev
|
|
1462
|
+
* @param technologyId - ID tehnologije
|
|
1463
|
+
* @param oldRequirement - Stari zahtev koji se menja
|
|
1464
|
+
* @param newRequirement - Novi zahtev koji zamenjuje stari
|
|
1465
|
+
* @returns Ažurirana tehnologija
|
|
1381
1466
|
*/
|
|
1382
|
-
async
|
|
1383
|
-
|
|
1384
|
-
|
|
1467
|
+
async updateRequirement(technologyId, oldRequirement, newRequirement) {
|
|
1468
|
+
await this.removeRequirement(technologyId, oldRequirement);
|
|
1469
|
+
return this.addRequirement(technologyId, newRequirement);
|
|
1470
|
+
}
|
|
1471
|
+
/**
|
|
1472
|
+
* Dodaje blokirajući uslov tehnologiji
|
|
1473
|
+
* @param technologyId - ID tehnologije
|
|
1474
|
+
* @param condition - Blokirajući uslov koji se dodaje
|
|
1475
|
+
* @returns Ažurirana tehnologija
|
|
1476
|
+
*/
|
|
1477
|
+
async addBlockingCondition(technologyId, condition) {
|
|
1478
|
+
const docRef = doc9(this.getTechnologiesRef(), technologyId);
|
|
1479
|
+
await updateDoc9(docRef, {
|
|
1480
|
+
blockingConditions: arrayUnion(condition),
|
|
1385
1481
|
updatedAt: /* @__PURE__ */ new Date()
|
|
1386
|
-
};
|
|
1387
|
-
|
|
1388
|
-
await updateDoc5(docRef, updateData);
|
|
1389
|
-
return this.getById(brandId);
|
|
1482
|
+
});
|
|
1483
|
+
return this.getById(technologyId);
|
|
1390
1484
|
}
|
|
1391
1485
|
/**
|
|
1392
|
-
*
|
|
1486
|
+
* Uklanja blokirajući uslov iz tehnologije
|
|
1487
|
+
* @param technologyId - ID tehnologije
|
|
1488
|
+
* @param condition - Blokirajući uslov koji se uklanja
|
|
1489
|
+
* @returns Ažurirana tehnologija
|
|
1393
1490
|
*/
|
|
1394
|
-
async
|
|
1395
|
-
|
|
1396
|
-
|
|
1491
|
+
async removeBlockingCondition(technologyId, condition) {
|
|
1492
|
+
const docRef = doc9(this.getTechnologiesRef(), technologyId);
|
|
1493
|
+
await updateDoc9(docRef, {
|
|
1494
|
+
blockingConditions: arrayRemove(condition),
|
|
1495
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
1397
1496
|
});
|
|
1497
|
+
return this.getById(technologyId);
|
|
1398
1498
|
}
|
|
1399
1499
|
/**
|
|
1400
|
-
*
|
|
1500
|
+
* Dodaje kontraindikaciju tehnologiji
|
|
1501
|
+
* @param technologyId - ID tehnologije
|
|
1502
|
+
* @param contraindication - Kontraindikacija koja se dodaje
|
|
1503
|
+
* @returns Ažurirana tehnologija
|
|
1401
1504
|
*/
|
|
1402
|
-
async
|
|
1403
|
-
const docRef =
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
};
|
|
1505
|
+
async addContraindication(technologyId, contraindication) {
|
|
1506
|
+
const docRef = doc9(this.getTechnologiesRef(), technologyId);
|
|
1507
|
+
await updateDoc9(docRef, {
|
|
1508
|
+
contraindications: arrayUnion(contraindication),
|
|
1509
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
1510
|
+
});
|
|
1511
|
+
return this.getById(technologyId);
|
|
1410
1512
|
}
|
|
1411
|
-
};
|
|
1412
|
-
|
|
1413
|
-
// src/backoffice/services/product.service.ts
|
|
1414
|
-
import {
|
|
1415
|
-
addDoc as addDoc6,
|
|
1416
|
-
collection as collection6,
|
|
1417
|
-
doc as doc6,
|
|
1418
|
-
getDoc as getDoc6,
|
|
1419
|
-
getDocs as getDocs6,
|
|
1420
|
-
query as query6,
|
|
1421
|
-
updateDoc as updateDoc6,
|
|
1422
|
-
where as where6
|
|
1423
|
-
} from "firebase/firestore";
|
|
1424
|
-
var ProductService = class extends BaseService {
|
|
1425
1513
|
/**
|
|
1426
|
-
*
|
|
1427
|
-
* @param technologyId - ID
|
|
1428
|
-
* @
|
|
1514
|
+
* Uklanja kontraindikaciju iz tehnologije
|
|
1515
|
+
* @param technologyId - ID tehnologije
|
|
1516
|
+
* @param contraindication - Kontraindikacija koja se uklanja
|
|
1517
|
+
* @returns Ažurirana tehnologija
|
|
1429
1518
|
*/
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
);
|
|
1519
|
+
async removeContraindication(technologyId, contraindication) {
|
|
1520
|
+
const docRef = doc9(this.getTechnologiesRef(), technologyId);
|
|
1521
|
+
await updateDoc9(docRef, {
|
|
1522
|
+
contraindications: arrayRemove(contraindication),
|
|
1523
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
1524
|
+
});
|
|
1525
|
+
return this.getById(technologyId);
|
|
1437
1526
|
}
|
|
1438
1527
|
/**
|
|
1439
|
-
*
|
|
1528
|
+
* Dodaje benefit tehnologiji
|
|
1529
|
+
* @param technologyId - ID tehnologije
|
|
1530
|
+
* @param benefit - Benefit koji se dodaje
|
|
1531
|
+
* @returns Ažurirana tehnologija
|
|
1440
1532
|
*/
|
|
1441
|
-
async
|
|
1442
|
-
const
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
updatedAt: now,
|
|
1449
|
-
isActive: true
|
|
1450
|
-
};
|
|
1451
|
-
const productRef = await addDoc6(
|
|
1452
|
-
this.getProductsRef(technologyId),
|
|
1453
|
-
newProduct
|
|
1454
|
-
);
|
|
1455
|
-
return { id: productRef.id, ...newProduct };
|
|
1533
|
+
async addBenefit(technologyId, benefit) {
|
|
1534
|
+
const docRef = doc9(this.getTechnologiesRef(), technologyId);
|
|
1535
|
+
await updateDoc9(docRef, {
|
|
1536
|
+
benefits: arrayUnion(benefit),
|
|
1537
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
1538
|
+
});
|
|
1539
|
+
return this.getById(technologyId);
|
|
1456
1540
|
}
|
|
1457
1541
|
/**
|
|
1458
|
-
*
|
|
1542
|
+
* Uklanja benefit iz tehnologije
|
|
1543
|
+
* @param technologyId - ID tehnologije
|
|
1544
|
+
* @param benefit - Benefit koji se uklanja
|
|
1545
|
+
* @returns Ažurirana tehnologija
|
|
1459
1546
|
*/
|
|
1460
|
-
async
|
|
1461
|
-
const
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
return
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1547
|
+
async removeBenefit(technologyId, benefit) {
|
|
1548
|
+
const docRef = doc9(this.getTechnologiesRef(), technologyId);
|
|
1549
|
+
await updateDoc9(docRef, {
|
|
1550
|
+
benefits: arrayRemove(benefit),
|
|
1551
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
1552
|
+
});
|
|
1553
|
+
return this.getById(technologyId);
|
|
1554
|
+
}
|
|
1555
|
+
/**
|
|
1556
|
+
* Vraća sve blokirajuće uslove za tehnologiju
|
|
1557
|
+
* @param technologyId - ID tehnologije
|
|
1558
|
+
* @returns Lista blokirajućih uslova
|
|
1559
|
+
*/
|
|
1560
|
+
async getBlockingConditions(technologyId) {
|
|
1561
|
+
const technology = await this.getById(technologyId);
|
|
1562
|
+
return (technology == null ? void 0 : technology.blockingConditions) || [];
|
|
1563
|
+
}
|
|
1564
|
+
/**
|
|
1565
|
+
* Vraća sve kontraindikacije za tehnologiju
|
|
1566
|
+
* @param technologyId - ID tehnologije
|
|
1567
|
+
* @returns Lista kontraindikacija
|
|
1568
|
+
*/
|
|
1569
|
+
async getContraindications(technologyId) {
|
|
1570
|
+
const technology = await this.getById(technologyId);
|
|
1571
|
+
return (technology == null ? void 0 : technology.contraindications) || [];
|
|
1472
1572
|
}
|
|
1473
1573
|
/**
|
|
1474
|
-
*
|
|
1574
|
+
* Vraća sve benefite za tehnologiju
|
|
1575
|
+
* @param technologyId - ID tehnologije
|
|
1576
|
+
* @returns Lista benefita
|
|
1475
1577
|
*/
|
|
1476
|
-
async
|
|
1477
|
-
const
|
|
1478
|
-
|
|
1479
|
-
const products = [];
|
|
1480
|
-
for (const techDoc of technologiesSnapshot.docs) {
|
|
1481
|
-
const q = query6(
|
|
1482
|
-
this.getProductsRef(techDoc.id),
|
|
1483
|
-
where6("brandId", "==", brandId),
|
|
1484
|
-
where6("isActive", "==", true)
|
|
1485
|
-
);
|
|
1486
|
-
const snapshot = await getDocs6(q);
|
|
1487
|
-
products.push(
|
|
1488
|
-
...snapshot.docs.map(
|
|
1489
|
-
(doc10) => ({
|
|
1490
|
-
id: doc10.id,
|
|
1491
|
-
...doc10.data()
|
|
1492
|
-
})
|
|
1493
|
-
)
|
|
1494
|
-
);
|
|
1495
|
-
}
|
|
1496
|
-
return products;
|
|
1578
|
+
async getBenefits(technologyId) {
|
|
1579
|
+
const technology = await this.getById(technologyId);
|
|
1580
|
+
return (technology == null ? void 0 : technology.benefits) || [];
|
|
1497
1581
|
}
|
|
1498
1582
|
/**
|
|
1499
|
-
*
|
|
1583
|
+
* Ažurira zahteve sertifikacije za tehnologiju
|
|
1584
|
+
* @param technologyId - ID tehnologije
|
|
1585
|
+
* @param certificationRequirement - Novi zahtevi sertifikacije
|
|
1586
|
+
* @returns Ažurirana tehnologija
|
|
1500
1587
|
*/
|
|
1501
|
-
async
|
|
1502
|
-
const
|
|
1503
|
-
|
|
1588
|
+
async updateCertificationRequirement(technologyId, certificationRequirement) {
|
|
1589
|
+
const docRef = doc9(this.getTechnologiesRef(), technologyId);
|
|
1590
|
+
await updateDoc9(docRef, {
|
|
1591
|
+
certificationRequirement,
|
|
1504
1592
|
updatedAt: /* @__PURE__ */ new Date()
|
|
1505
|
-
};
|
|
1506
|
-
|
|
1507
|
-
await updateDoc6(docRef, updateData);
|
|
1508
|
-
return this.getById(technologyId, productId);
|
|
1593
|
+
});
|
|
1594
|
+
return this.getById(technologyId);
|
|
1509
1595
|
}
|
|
1510
1596
|
/**
|
|
1511
|
-
*
|
|
1597
|
+
* Vraća zahteve sertifikacije za tehnologiju
|
|
1598
|
+
* @param technologyId - ID tehnologije
|
|
1599
|
+
* @returns Zahtevi sertifikacije ili null ako tehnologija ne postoji
|
|
1512
1600
|
*/
|
|
1513
|
-
async
|
|
1514
|
-
await this.
|
|
1515
|
-
|
|
1516
|
-
});
|
|
1601
|
+
async getCertificationRequirement(technologyId) {
|
|
1602
|
+
const technology = await this.getById(technologyId);
|
|
1603
|
+
return (technology == null ? void 0 : technology.certificationRequirement) || null;
|
|
1517
1604
|
}
|
|
1518
1605
|
/**
|
|
1519
|
-
*
|
|
1606
|
+
* Proverava da li doktor ima odgovarajuću sertifikaciju za izvođenje tehnologije
|
|
1607
|
+
*
|
|
1608
|
+
* @param requiredCertification - Zahtevana sertifikacija za tehnologiju
|
|
1609
|
+
* @param practitionerCertification - Sertifikacija zdravstvenog radnika
|
|
1610
|
+
* @returns true ako zdravstveni radnik ima odgovarajuću sertifikaciju, false ako nema
|
|
1611
|
+
*
|
|
1612
|
+
* @example
|
|
1613
|
+
* const isValid = technologyService.validateCertification(
|
|
1614
|
+
* {
|
|
1615
|
+
* minimumLevel: CertificationLevel.DOCTOR,
|
|
1616
|
+
* requiredSpecialties: [CertificationSpecialty.INJECTABLES]
|
|
1617
|
+
* },
|
|
1618
|
+
* {
|
|
1619
|
+
* level: CertificationLevel.SPECIALIST,
|
|
1620
|
+
* specialties: [CertificationSpecialty.INJECTABLES, CertificationSpecialty.LASER]
|
|
1621
|
+
* }
|
|
1622
|
+
* );
|
|
1520
1623
|
*/
|
|
1521
|
-
|
|
1522
|
-
const
|
|
1523
|
-
|
|
1524
|
-
|
|
1624
|
+
validateCertification(requiredCertification, practitionerCertification) {
|
|
1625
|
+
const doctorLevel = Object.values(CertificationLevel).indexOf(
|
|
1626
|
+
practitionerCertification.level
|
|
1627
|
+
);
|
|
1628
|
+
const requiredLevel = Object.values(CertificationLevel).indexOf(
|
|
1629
|
+
requiredCertification.minimumLevel
|
|
1630
|
+
);
|
|
1631
|
+
if (doctorLevel < requiredLevel) return false;
|
|
1632
|
+
const requiredSpecialties = requiredCertification.requiredSpecialties || [];
|
|
1633
|
+
if (requiredSpecialties.length > 0) {
|
|
1634
|
+
const doctorSpecialties = practitionerCertification.specialties;
|
|
1635
|
+
const hasAllRequiredSpecialties = requiredSpecialties.every(
|
|
1636
|
+
(requiredSpecialty) => doctorSpecialties.includes(requiredSpecialty)
|
|
1637
|
+
);
|
|
1638
|
+
if (!hasAllRequiredSpecialties) return false;
|
|
1639
|
+
}
|
|
1640
|
+
return true;
|
|
1641
|
+
}
|
|
1642
|
+
/**
|
|
1643
|
+
* Vraća sve tehnologije koje je zdravstveni radnik sertifikovan da izvodi
|
|
1644
|
+
* zajedno sa listama dozvoljenih familija, kategorija i podkategorija
|
|
1645
|
+
*
|
|
1646
|
+
* @param practitioner - Profil zdravstvenog radnika
|
|
1647
|
+
* @returns Objekat koji sadrži:
|
|
1648
|
+
* - technologies: Lista tehnologija koje zdravstveni radnik može da izvodi
|
|
1649
|
+
* - families: Lista familija procedura koje zdravstveni radnik može da izvodi
|
|
1650
|
+
* - categories: Lista ID-eva kategorija koje zdravstveni radnik može da izvodi
|
|
1651
|
+
* - subcategories: Lista ID-eva podkategorija koje zdravstveni radnik može da izvodi
|
|
1652
|
+
*
|
|
1653
|
+
* @example
|
|
1654
|
+
* const practitioner = {
|
|
1655
|
+
* certification: {
|
|
1656
|
+
* level: CertificationLevel.DOCTOR,
|
|
1657
|
+
* specialties: [CertificationSpecialty.INJECTABLES]
|
|
1658
|
+
* }
|
|
1659
|
+
* };
|
|
1660
|
+
* const allowedTechnologies = await technologyService.getAllowedTechnologies(practitioner);
|
|
1661
|
+
* console.log(allowedTechnologies.families); // [ProcedureFamily.AESTHETICS]
|
|
1662
|
+
* console.log(allowedTechnologies.categories); // ["category1", "category2"]
|
|
1663
|
+
* console.log(allowedTechnologies.subcategories); // ["subcategory1", "subcategory2"]
|
|
1664
|
+
*/
|
|
1665
|
+
async getAllowedTechnologies(practitioner) {
|
|
1666
|
+
const allTechnologies = await this.getAll();
|
|
1667
|
+
const allowedTechnologies = allTechnologies.filter(
|
|
1668
|
+
(technology) => this.validateCertification(
|
|
1669
|
+
technology.certificationRequirement,
|
|
1670
|
+
practitioner.certification
|
|
1671
|
+
)
|
|
1672
|
+
);
|
|
1673
|
+
const families = [...new Set(allowedTechnologies.map((t) => t.family))];
|
|
1674
|
+
const categories = [
|
|
1675
|
+
...new Set(allowedTechnologies.map((t) => t.categoryId))
|
|
1676
|
+
];
|
|
1677
|
+
const subcategories = [
|
|
1678
|
+
...new Set(allowedTechnologies.map((t) => t.subcategoryId))
|
|
1679
|
+
];
|
|
1525
1680
|
return {
|
|
1526
|
-
|
|
1527
|
-
|
|
1681
|
+
technologies: allowedTechnologies,
|
|
1682
|
+
families,
|
|
1683
|
+
categories,
|
|
1684
|
+
subcategories
|
|
1528
1685
|
};
|
|
1529
1686
|
}
|
|
1530
1687
|
};
|
|
1531
1688
|
|
|
1532
|
-
// src/
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1689
|
+
// src/backoffice/types/static/blocking-condition.types.ts
|
|
1690
|
+
var BlockingCondition = /* @__PURE__ */ ((BlockingCondition2) => {
|
|
1691
|
+
BlockingCondition2["PREGNANCY"] = "pregnancy";
|
|
1692
|
+
BlockingCondition2["BREASTFEEDING"] = "breastfeeding";
|
|
1693
|
+
BlockingCondition2["ACTIVE_INFECTION"] = "active_infection";
|
|
1694
|
+
BlockingCondition2["SKIN_CONDITION"] = "skin_condition";
|
|
1695
|
+
BlockingCondition2["AUTOIMMUNE_DISEASE"] = "autoimmune_disease";
|
|
1696
|
+
BlockingCondition2["BLOOD_THINNERS"] = "blood_thinners";
|
|
1697
|
+
BlockingCondition2["RECENT_SURGERY"] = "recent_surgery";
|
|
1698
|
+
BlockingCondition2["DIABETES"] = "diabetes";
|
|
1699
|
+
BlockingCondition2["HEART_CONDITION"] = "heart_condition";
|
|
1700
|
+
BlockingCondition2["HIGH_BLOOD_PRESSURE"] = "high_blood_pressure";
|
|
1701
|
+
BlockingCondition2["KELOID_SCARRING"] = "keloid_scarring";
|
|
1702
|
+
BlockingCondition2["METAL_IMPLANTS"] = "metal_implants";
|
|
1703
|
+
BlockingCondition2["PACEMAKER"] = "pacemaker";
|
|
1704
|
+
BlockingCondition2["CANCER"] = "cancer";
|
|
1705
|
+
BlockingCondition2["EPILEPSY"] = "epilepsy";
|
|
1706
|
+
return BlockingCondition2;
|
|
1707
|
+
})(BlockingCondition || {});
|
|
1708
|
+
|
|
1709
|
+
// src/backoffice/types/static/contraindication.types.ts
|
|
1710
|
+
var Contraindication = /* @__PURE__ */ ((Contraindication2) => {
|
|
1711
|
+
Contraindication2["SENSITIVE_SKIN"] = "sensitive_skin";
|
|
1712
|
+
Contraindication2["RECENT_TANNING"] = "recent_tanning";
|
|
1713
|
+
Contraindication2["RECENT_BOTOX"] = "recent_botox";
|
|
1714
|
+
Contraindication2["RECENT_FILLERS"] = "recent_fillers";
|
|
1715
|
+
Contraindication2["SKIN_ALLERGIES"] = "skin_allergies";
|
|
1716
|
+
Contraindication2["MEDICATIONS"] = "medications";
|
|
1717
|
+
Contraindication2["RECENT_CHEMICAL_PEEL"] = "recent_chemical_peel";
|
|
1718
|
+
Contraindication2["RECENT_LASER"] = "recent_laser";
|
|
1719
|
+
Contraindication2["SKIN_INFLAMMATION"] = "skin_inflammation";
|
|
1720
|
+
Contraindication2["OPEN_WOUNDS"] = "open_wounds";
|
|
1721
|
+
Contraindication2["HERPES_SIMPLEX"] = "herpes_simplex";
|
|
1722
|
+
Contraindication2["COLD_SORES"] = "cold_sores";
|
|
1723
|
+
return Contraindication2;
|
|
1724
|
+
})(Contraindication || {});
|
|
1725
|
+
|
|
1726
|
+
// src/backoffice/types/static/procedure-family.types.ts
|
|
1727
|
+
var ProcedureFamily = /* @__PURE__ */ ((ProcedureFamily2) => {
|
|
1728
|
+
ProcedureFamily2["AESTHETICS"] = "aesthetics";
|
|
1729
|
+
ProcedureFamily2["SURGERY"] = "surgery";
|
|
1730
|
+
return ProcedureFamily2;
|
|
1731
|
+
})(ProcedureFamily || {});
|
|
1732
|
+
|
|
1733
|
+
// src/backoffice/types/static/treatment-benefit.types.ts
|
|
1734
|
+
var TreatmentBenefit = /* @__PURE__ */ ((TreatmentBenefit2) => {
|
|
1735
|
+
TreatmentBenefit2["WRINKLE_REDUCTION"] = "wrinkle_reduction";
|
|
1736
|
+
TreatmentBenefit2["SKIN_TIGHTENING"] = "skin_tightening";
|
|
1737
|
+
TreatmentBenefit2["COLLAGEN_PRODUCTION"] = "collagen_production";
|
|
1738
|
+
TreatmentBenefit2["ACNE_REDUCTION"] = "acne_reduction";
|
|
1739
|
+
TreatmentBenefit2["SCAR_REDUCTION"] = "scar_reduction";
|
|
1740
|
+
TreatmentBenefit2["PIGMENTATION_IMPROVEMENT"] = "pigmentation_improvement";
|
|
1741
|
+
TreatmentBenefit2["HAIR_REMOVAL"] = "hair_removal";
|
|
1742
|
+
TreatmentBenefit2["MUSCLE_TONING"] = "muscle_toning";
|
|
1743
|
+
TreatmentBenefit2["FAT_REDUCTION"] = "fat_reduction";
|
|
1744
|
+
TreatmentBenefit2["CELLULITE_REDUCTION"] = "cellulite_reduction";
|
|
1745
|
+
TreatmentBenefit2["SKIN_REJUVENATION"] = "skin_rejuvenation";
|
|
1746
|
+
TreatmentBenefit2["PORE_REDUCTION"] = "pore_reduction";
|
|
1747
|
+
TreatmentBenefit2["TEXTURE_IMPROVEMENT"] = "texture_improvement";
|
|
1748
|
+
TreatmentBenefit2["HYDRATION_BOOST"] = "hydration_boost";
|
|
1749
|
+
TreatmentBenefit2["CIRCULATION_IMPROVEMENT"] = "circulation_improvement";
|
|
1750
|
+
return TreatmentBenefit2;
|
|
1751
|
+
})(TreatmentBenefit || {});
|
|
1752
|
+
|
|
1753
|
+
// src/backoffice/validations/schemas.ts
|
|
1754
|
+
import { z as z2 } from "zod";
|
|
1755
|
+
var blockingConditionSchema = z2.nativeEnum(BlockingCondition);
|
|
1756
|
+
var contraindicationSchema = z2.nativeEnum(Contraindication);
|
|
1757
|
+
var treatmentBenefitSchema = z2.nativeEnum(TreatmentBenefit);
|
|
1758
|
+
var procedureFamilySchema = z2.nativeEnum(ProcedureFamily);
|
|
1759
|
+
var timeUnitSchema = z2.nativeEnum(TimeUnit);
|
|
1760
|
+
var requirementTypeSchema = z2.nativeEnum(RequirementType);
|
|
1761
|
+
var certificationLevelSchema = z2.nativeEnum(CertificationLevel);
|
|
1762
|
+
var certificationSpecialtySchema = z2.nativeEnum(
|
|
1763
|
+
CertificationSpecialty
|
|
1764
|
+
);
|
|
1765
|
+
var certificationRequirementSchema = z2.object({
|
|
1766
|
+
minimumLevel: certificationLevelSchema,
|
|
1767
|
+
requiredSpecialties: z2.array(certificationSpecialtySchema).max(5, "Maximum 5 specialties allowed").optional()
|
|
1768
|
+
});
|
|
1769
|
+
var timeframeSchema = z2.object({
|
|
1770
|
+
duration: z2.number().min(1, "Duration must be positive"),
|
|
1771
|
+
unit: timeUnitSchema,
|
|
1772
|
+
notifyAt: z2.array(z2.number()).min(1, "At least one notification point is required")
|
|
1773
|
+
});
|
|
1774
|
+
var requirementSchema = z2.object({
|
|
1775
|
+
name: z2.string().min(1, "Name is required").max(100, "Name is too long"),
|
|
1776
|
+
description: z2.string().min(1, "Description is required"),
|
|
1777
|
+
type: requirementTypeSchema,
|
|
1778
|
+
timeframe: timeframeSchema,
|
|
1779
|
+
importance: z2.enum(["low", "medium", "high"]),
|
|
1780
|
+
isActive: z2.boolean().default(true)
|
|
1781
|
+
});
|
|
1782
|
+
var technologyRequirementsSchema = z2.object({
|
|
1783
|
+
pre: z2.array(requirementSchema),
|
|
1784
|
+
post: z2.array(requirementSchema)
|
|
1785
|
+
});
|
|
1786
|
+
var technologySchema = z2.object({
|
|
1787
|
+
name: z2.string().min(1, "Name is required").max(100, "Name is too long"),
|
|
1788
|
+
description: z2.string().max(1e3, "Description is too long").optional(),
|
|
1789
|
+
technicalDetails: z2.string().max(2e3, "Technical details are too long").optional(),
|
|
1790
|
+
family: procedureFamilySchema,
|
|
1791
|
+
categoryId: z2.string().min(1, "Category ID is required"),
|
|
1792
|
+
subcategoryId: z2.string().min(1, "Subcategory ID is required"),
|
|
1793
|
+
requirements: technologyRequirementsSchema.default({
|
|
1794
|
+
pre: [],
|
|
1795
|
+
post: []
|
|
1796
|
+
}),
|
|
1797
|
+
blockingConditions: z2.array(blockingConditionSchema),
|
|
1798
|
+
contraindications: z2.array(contraindicationSchema),
|
|
1799
|
+
documentationTemplates: z2.array(documentTemplateSchema),
|
|
1800
|
+
benefits: z2.array(treatmentBenefitSchema),
|
|
1801
|
+
certificationRequirement: certificationRequirementSchema,
|
|
1802
|
+
isActive: z2.boolean().default(true)
|
|
1803
|
+
});
|
|
1804
|
+
var categorySchema = z2.object({
|
|
1805
|
+
name: z2.string().min(1, "Name is required").max(100, "Name is too long"),
|
|
1806
|
+
description: z2.string().optional(),
|
|
1807
|
+
family: procedureFamilySchema,
|
|
1808
|
+
isActive: z2.boolean().default(true)
|
|
1809
|
+
});
|
|
1810
|
+
var subcategorySchema = z2.object({
|
|
1811
|
+
name: z2.string().min(1, "Name is required").max(100, "Name is too long"),
|
|
1812
|
+
description: z2.string().optional(),
|
|
1813
|
+
categoryId: z2.string().min(1, "Category ID is required"),
|
|
1814
|
+
isActive: z2.boolean().default(true)
|
|
1815
|
+
});
|
|
1816
|
+
var categoryUpdateSchema = categorySchema.partial();
|
|
1817
|
+
var subcategoryUpdateSchema = subcategorySchema.partial();
|
|
1818
|
+
var technologyUpdateSchema = technologySchema.partial();
|
|
1819
|
+
var requirementUpdateSchema = requirementSchema.partial();
|
|
1820
|
+
|
|
1821
|
+
// src/backoffice/constants/certification.constants.ts
|
|
1822
|
+
var DEFAULT_CERTIFICATION_REQUIREMENT2 = {
|
|
1823
|
+
minimumLevel: "aesthetician" /* AESTHETICIAN */,
|
|
1824
|
+
requiredSpecialties: []
|
|
1825
|
+
};
|
|
1826
|
+
|
|
1827
|
+
// src/backoffice/errors/backoffice.errors.ts
|
|
1828
|
+
var BackofficeError = class extends Error {
|
|
1829
|
+
constructor(message) {
|
|
1830
|
+
super(message);
|
|
1831
|
+
this.name = "BackofficeError";
|
|
1554
1832
|
}
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
*/
|
|
1561
|
-
async createTemplate(data, userId) {
|
|
1562
|
-
const validatedData = createDocumentTemplateSchema.parse(data);
|
|
1563
|
-
const templateId = this.generateId();
|
|
1564
|
-
const elementsWithIds = validatedData.elements.map((element) => ({
|
|
1565
|
-
...element,
|
|
1566
|
-
id: this.generateId()
|
|
1567
|
-
}));
|
|
1568
|
-
const now = Date.now();
|
|
1569
|
-
const template = {
|
|
1570
|
-
id: templateId,
|
|
1571
|
-
title: validatedData.title,
|
|
1572
|
-
description: validatedData.description,
|
|
1573
|
-
elements: elementsWithIds,
|
|
1574
|
-
createdAt: now,
|
|
1575
|
-
updatedAt: now,
|
|
1576
|
-
createdBy: userId,
|
|
1577
|
-
version: 1,
|
|
1578
|
-
isActive: true,
|
|
1579
|
-
tags: validatedData.tags || [],
|
|
1580
|
-
isUserForm: validatedData.isUserForm || false,
|
|
1581
|
-
isRequired: validatedData.isRequired || false,
|
|
1582
|
-
sortingOrder: validatedData.sortingOrder || 0
|
|
1583
|
-
};
|
|
1584
|
-
const docRef = doc7(this.collectionRef, templateId);
|
|
1585
|
-
await setDoc(docRef, template);
|
|
1586
|
-
return template;
|
|
1833
|
+
};
|
|
1834
|
+
var CategoryError = class extends BackofficeError {
|
|
1835
|
+
constructor(message) {
|
|
1836
|
+
super(message);
|
|
1837
|
+
this.name = "CategoryError";
|
|
1587
1838
|
}
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
*/
|
|
1594
|
-
async getTemplateById(templateId, version) {
|
|
1595
|
-
const docRef = doc7(this.collectionRef, templateId);
|
|
1596
|
-
const docSnap = await getDoc7(docRef);
|
|
1597
|
-
if (!docSnap.exists()) {
|
|
1598
|
-
return null;
|
|
1599
|
-
}
|
|
1600
|
-
const currentTemplate = docSnap.data();
|
|
1601
|
-
if (version === void 0) {
|
|
1602
|
-
return currentTemplate;
|
|
1603
|
-
}
|
|
1604
|
-
if (currentTemplate.version === version) {
|
|
1605
|
-
return currentTemplate;
|
|
1606
|
-
}
|
|
1607
|
-
try {
|
|
1608
|
-
const versionTemplate = await this.getTemplateVersion(
|
|
1609
|
-
templateId,
|
|
1610
|
-
version
|
|
1611
|
-
);
|
|
1612
|
-
if (versionTemplate) {
|
|
1613
|
-
return versionTemplate;
|
|
1614
|
-
}
|
|
1615
|
-
} catch (error) {
|
|
1616
|
-
console.error(`Error getting template version ${version}:`, error);
|
|
1617
|
-
}
|
|
1618
|
-
return null;
|
|
1839
|
+
};
|
|
1840
|
+
var CategoryNotFoundError = class extends CategoryError {
|
|
1841
|
+
constructor(id) {
|
|
1842
|
+
super(`Kategorija sa ID-em ${id} nije prona\u0111ena`);
|
|
1843
|
+
this.name = "CategoryNotFoundError";
|
|
1619
1844
|
}
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
*/
|
|
1626
|
-
async updateTemplate(templateId, data) {
|
|
1627
|
-
var _a, _b, _c;
|
|
1628
|
-
const validatedData = updateDocumentTemplateSchema.parse(data);
|
|
1629
|
-
console.log("Validated data", validatedData);
|
|
1630
|
-
const template = await this.getTemplateById(templateId);
|
|
1631
|
-
if (!template) {
|
|
1632
|
-
throw new Error(`Template with ID ${templateId} not found`);
|
|
1633
|
-
}
|
|
1634
|
-
const versionsCollectionRef = collection7(
|
|
1635
|
-
this.db,
|
|
1636
|
-
`${DOCUMENTATION_TEMPLATES_COLLECTION}/${templateId}/versions`
|
|
1637
|
-
);
|
|
1638
|
-
const versionDocRef = doc7(
|
|
1639
|
-
versionsCollectionRef,
|
|
1640
|
-
template.version.toString()
|
|
1641
|
-
);
|
|
1642
|
-
await setDoc(versionDocRef, template);
|
|
1643
|
-
let updatedElements = template.elements;
|
|
1644
|
-
if (validatedData.elements) {
|
|
1645
|
-
updatedElements = validatedData.elements.map((element) => ({
|
|
1646
|
-
...element,
|
|
1647
|
-
id: element.id || this.generateId()
|
|
1648
|
-
}));
|
|
1649
|
-
}
|
|
1650
|
-
const updatePayload = {
|
|
1651
|
-
elements: updatedElements,
|
|
1652
|
-
updatedAt: Date.now(),
|
|
1653
|
-
version: template.version + 1
|
|
1654
|
-
};
|
|
1655
|
-
if (validatedData.title !== void 0)
|
|
1656
|
-
updatePayload.title = validatedData.title;
|
|
1657
|
-
if (validatedData.description !== void 0)
|
|
1658
|
-
updatePayload.description = validatedData.description;
|
|
1659
|
-
if (validatedData.isActive !== void 0)
|
|
1660
|
-
updatePayload.isActive = validatedData.isActive;
|
|
1661
|
-
if (validatedData.tags !== void 0)
|
|
1662
|
-
updatePayload.tags = validatedData.tags;
|
|
1663
|
-
updatePayload.isUserForm = (_a = validatedData.isUserForm) != null ? _a : false;
|
|
1664
|
-
updatePayload.isRequired = (_b = validatedData.isRequired) != null ? _b : false;
|
|
1665
|
-
updatePayload.sortingOrder = (_c = validatedData.sortingOrder) != null ? _c : 0;
|
|
1666
|
-
const docRef = doc7(this.collectionRef, templateId);
|
|
1667
|
-
console.log("Update payload", updatePayload);
|
|
1668
|
-
await updateDoc7(docRef, updatePayload);
|
|
1669
|
-
return { ...template, ...updatePayload };
|
|
1845
|
+
};
|
|
1846
|
+
var InvalidCategoryDataError = class extends CategoryError {
|
|
1847
|
+
constructor(message) {
|
|
1848
|
+
super(`Neva\u017Ee\u0107i podaci za kategoriju: ${message}`);
|
|
1849
|
+
this.name = "InvalidCategoryDataError";
|
|
1670
1850
|
}
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
*/
|
|
1677
|
-
async getTemplateVersion(templateId, versionNumber) {
|
|
1678
|
-
const versionDocRef = doc7(
|
|
1679
|
-
this.db,
|
|
1680
|
-
`${DOCUMENTATION_TEMPLATES_COLLECTION}/${templateId}/versions/${versionNumber}`
|
|
1681
|
-
);
|
|
1682
|
-
const versionDocSnap = await getDoc7(versionDocRef);
|
|
1683
|
-
if (!versionDocSnap.exists()) {
|
|
1684
|
-
return null;
|
|
1685
|
-
}
|
|
1686
|
-
return versionDocSnap.data();
|
|
1851
|
+
};
|
|
1852
|
+
var SubcategoryError = class extends BackofficeError {
|
|
1853
|
+
constructor(message) {
|
|
1854
|
+
super(message);
|
|
1855
|
+
this.name = "SubcategoryError";
|
|
1687
1856
|
}
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
async getTemplateOldVersions(templateId) {
|
|
1694
|
-
const versionsCollectionRef = collection7(
|
|
1695
|
-
this.db,
|
|
1696
|
-
`${DOCUMENTATION_TEMPLATES_COLLECTION}/${templateId}/versions`
|
|
1697
|
-
);
|
|
1698
|
-
const q = query7(versionsCollectionRef, orderBy("version", "desc"));
|
|
1699
|
-
const querySnapshot = await getDocs7(q);
|
|
1700
|
-
const versions = [];
|
|
1701
|
-
querySnapshot.forEach((doc10) => {
|
|
1702
|
-
versions.push(doc10.data());
|
|
1703
|
-
});
|
|
1704
|
-
return versions;
|
|
1857
|
+
};
|
|
1858
|
+
var SubcategoryNotFoundError = class extends SubcategoryError {
|
|
1859
|
+
constructor(id) {
|
|
1860
|
+
super(`Podkategorija sa ID-em ${id} nije prona\u0111ena`);
|
|
1861
|
+
this.name = "SubcategoryNotFoundError";
|
|
1705
1862
|
}
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
const docRef = doc7(this.collectionRef, templateId);
|
|
1712
|
-
await deleteDoc(docRef);
|
|
1863
|
+
};
|
|
1864
|
+
var InvalidSubcategoryDataError = class extends SubcategoryError {
|
|
1865
|
+
constructor(message) {
|
|
1866
|
+
super(`Neva\u017Ee\u0107i podaci za podkategoriju: ${message}`);
|
|
1867
|
+
this.name = "InvalidSubcategoryDataError";
|
|
1713
1868
|
}
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
limit(pageSize)
|
|
1726
|
-
);
|
|
1727
|
-
if (lastDoc) {
|
|
1728
|
-
q = query7(q, startAfter(lastDoc));
|
|
1729
|
-
}
|
|
1730
|
-
const querySnapshot = await getDocs7(q);
|
|
1731
|
-
const templates = [];
|
|
1732
|
-
let lastVisible = null;
|
|
1733
|
-
querySnapshot.forEach((doc10) => {
|
|
1734
|
-
templates.push(doc10.data());
|
|
1735
|
-
lastVisible = doc10;
|
|
1736
|
-
});
|
|
1737
|
-
return {
|
|
1738
|
-
templates,
|
|
1739
|
-
lastDoc: lastVisible
|
|
1740
|
-
};
|
|
1869
|
+
};
|
|
1870
|
+
var TechnologyError = class extends BackofficeError {
|
|
1871
|
+
constructor(message) {
|
|
1872
|
+
super(message);
|
|
1873
|
+
this.name = "TechnologyError";
|
|
1874
|
+
}
|
|
1875
|
+
};
|
|
1876
|
+
var TechnologyNotFoundError = class extends TechnologyError {
|
|
1877
|
+
constructor(id) {
|
|
1878
|
+
super(`Tehnologija sa ID-em ${id} nije prona\u0111ena`);
|
|
1879
|
+
this.name = "TechnologyNotFoundError";
|
|
1741
1880
|
}
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
* @returns Array of templates and the last document for pagination
|
|
1748
|
-
*/
|
|
1749
|
-
async getTemplatesByTags(tags, pageSize = 20, lastDoc) {
|
|
1750
|
-
let q = query7(
|
|
1751
|
-
this.collectionRef,
|
|
1752
|
-
where7("isActive", "==", true),
|
|
1753
|
-
where7("tags", "array-contains-any", tags),
|
|
1754
|
-
orderBy("updatedAt", "desc"),
|
|
1755
|
-
limit(pageSize)
|
|
1756
|
-
);
|
|
1757
|
-
if (lastDoc) {
|
|
1758
|
-
q = query7(q, startAfter(lastDoc));
|
|
1759
|
-
}
|
|
1760
|
-
const querySnapshot = await getDocs7(q);
|
|
1761
|
-
const templates = [];
|
|
1762
|
-
let lastVisible = null;
|
|
1763
|
-
querySnapshot.forEach((doc10) => {
|
|
1764
|
-
templates.push(doc10.data());
|
|
1765
|
-
lastVisible = doc10;
|
|
1766
|
-
});
|
|
1767
|
-
return {
|
|
1768
|
-
templates,
|
|
1769
|
-
lastDoc: lastVisible
|
|
1770
|
-
};
|
|
1881
|
+
};
|
|
1882
|
+
var InvalidTechnologyDataError = class extends TechnologyError {
|
|
1883
|
+
constructor(message) {
|
|
1884
|
+
super(`Neva\u017Ee\u0107i podaci za tehnologiju: ${message}`);
|
|
1885
|
+
this.name = "InvalidTechnologyDataError";
|
|
1771
1886
|
}
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
* @returns Array of templates and the last document for pagination
|
|
1778
|
-
*/
|
|
1779
|
-
async getTemplatesByCreator(userId, pageSize = 20, lastDoc) {
|
|
1780
|
-
let q = query7(
|
|
1781
|
-
this.collectionRef,
|
|
1782
|
-
where7("createdBy", "==", userId),
|
|
1783
|
-
orderBy("updatedAt", "desc"),
|
|
1784
|
-
limit(pageSize)
|
|
1785
|
-
);
|
|
1786
|
-
if (lastDoc) {
|
|
1787
|
-
q = query7(q, startAfter(lastDoc));
|
|
1788
|
-
}
|
|
1789
|
-
const querySnapshot = await getDocs7(q);
|
|
1790
|
-
const templates = [];
|
|
1791
|
-
let lastVisible = null;
|
|
1792
|
-
querySnapshot.forEach((doc10) => {
|
|
1793
|
-
templates.push(doc10.data());
|
|
1794
|
-
lastVisible = doc10;
|
|
1795
|
-
});
|
|
1796
|
-
return {
|
|
1797
|
-
templates,
|
|
1798
|
-
lastDoc: lastVisible
|
|
1799
|
-
};
|
|
1887
|
+
};
|
|
1888
|
+
var RequirementError = class extends BackofficeError {
|
|
1889
|
+
constructor(message) {
|
|
1890
|
+
super(message);
|
|
1891
|
+
this.name = "RequirementError";
|
|
1800
1892
|
}
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
async getAllTemplatesForSelection(options) {
|
|
1807
|
-
let q = query7(
|
|
1808
|
-
this.collectionRef,
|
|
1809
|
-
where7("isActive", "==", true),
|
|
1810
|
-
orderBy("updatedAt", "desc")
|
|
1811
|
-
);
|
|
1812
|
-
if ((options == null ? void 0 : options.isUserForm) !== void 0) {
|
|
1813
|
-
q = query7(q, where7("isUserForm", "==", options.isUserForm));
|
|
1814
|
-
}
|
|
1815
|
-
if ((options == null ? void 0 : options.isRequired) !== void 0) {
|
|
1816
|
-
q = query7(q, where7("isRequired", "==", options.isRequired));
|
|
1817
|
-
}
|
|
1818
|
-
const querySnapshot = await getDocs7(q);
|
|
1819
|
-
const templates = [];
|
|
1820
|
-
querySnapshot.forEach((doc10) => {
|
|
1821
|
-
templates.push(doc10.data());
|
|
1822
|
-
});
|
|
1823
|
-
return templates;
|
|
1893
|
+
};
|
|
1894
|
+
var RequirementNotFoundError = class extends RequirementError {
|
|
1895
|
+
constructor(id) {
|
|
1896
|
+
super(`Zahtev sa ID-em ${id} nije prona\u0111en`);
|
|
1897
|
+
this.name = "RequirementNotFoundError";
|
|
1824
1898
|
}
|
|
1825
1899
|
};
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
doc as doc9,
|
|
1831
|
-
getDoc as getDoc9,
|
|
1832
|
-
getDocs as getDocs9,
|
|
1833
|
-
setDoc as setDoc3,
|
|
1834
|
-
updateDoc as updateDoc9,
|
|
1835
|
-
query as query9,
|
|
1836
|
-
orderBy as orderBy3,
|
|
1837
|
-
limit as limit3,
|
|
1838
|
-
startAfter as startAfter2
|
|
1839
|
-
} from "firebase/firestore";
|
|
1840
|
-
|
|
1841
|
-
// src/services/media/media.service.ts
|
|
1842
|
-
import { Timestamp as Timestamp2 } from "firebase/firestore";
|
|
1843
|
-
import {
|
|
1844
|
-
ref,
|
|
1845
|
-
uploadBytes,
|
|
1846
|
-
getDownloadURL,
|
|
1847
|
-
deleteObject,
|
|
1848
|
-
getBytes
|
|
1849
|
-
} from "firebase/storage";
|
|
1850
|
-
import {
|
|
1851
|
-
doc as doc8,
|
|
1852
|
-
getDoc as getDoc8,
|
|
1853
|
-
setDoc as setDoc2,
|
|
1854
|
-
updateDoc as updateDoc8,
|
|
1855
|
-
collection as collection8,
|
|
1856
|
-
query as query8,
|
|
1857
|
-
where as where8,
|
|
1858
|
-
limit as limit2,
|
|
1859
|
-
getDocs as getDocs8,
|
|
1860
|
-
deleteDoc as deleteDoc2,
|
|
1861
|
-
orderBy as orderBy2
|
|
1862
|
-
} from "firebase/firestore";
|
|
1863
|
-
|
|
1864
|
-
// src/backoffice/services/documentation-template.service.ts
|
|
1865
|
-
var DocumentationTemplateService2 = class {
|
|
1866
|
-
/**
|
|
1867
|
-
* Constructor for DocumentationTemplateService
|
|
1868
|
-
* @param db - Firestore instance
|
|
1869
|
-
* @param auth - Firebase Auth instance
|
|
1870
|
-
* @param app - Firebase App instance
|
|
1871
|
-
*/
|
|
1872
|
-
constructor(db, auth, app) {
|
|
1873
|
-
this.apiService = new DocumentationTemplateService(db, auth, app);
|
|
1900
|
+
var InvalidRequirementDataError = class extends RequirementError {
|
|
1901
|
+
constructor(message) {
|
|
1902
|
+
super(`Neva\u017Ee\u0107i podaci za zahtev: ${message}`);
|
|
1903
|
+
this.name = "InvalidRequirementDataError";
|
|
1874
1904
|
}
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
*/
|
|
1881
|
-
async createTemplate(data, userId) {
|
|
1882
|
-
return this.apiService.createTemplate(data, userId);
|
|
1905
|
+
};
|
|
1906
|
+
var InvalidTimeframeError = class extends RequirementError {
|
|
1907
|
+
constructor(message) {
|
|
1908
|
+
super(`Invalid timeframe: ${message}`);
|
|
1909
|
+
this.name = "InvalidTimeframeError";
|
|
1883
1910
|
}
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
*/
|
|
1890
|
-
async getTemplateById(templateId, version) {
|
|
1891
|
-
return this.apiService.getTemplateById(templateId, version);
|
|
1911
|
+
};
|
|
1912
|
+
var RelationshipError = class extends BackofficeError {
|
|
1913
|
+
constructor(message) {
|
|
1914
|
+
super(message);
|
|
1915
|
+
this.name = "RelationshipError";
|
|
1892
1916
|
}
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
*/
|
|
1899
|
-
async updateTemplate(templateId, data) {
|
|
1900
|
-
return this.apiService.updateTemplate(templateId, data);
|
|
1917
|
+
};
|
|
1918
|
+
var InvalidHierarchyError = class extends RelationshipError {
|
|
1919
|
+
constructor(message) {
|
|
1920
|
+
super(`Invalid hierarchy: ${message}`);
|
|
1921
|
+
this.name = "InvalidHierarchyError";
|
|
1901
1922
|
}
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
return this.apiService.deleteTemplate(templateId);
|
|
1923
|
+
};
|
|
1924
|
+
var CircularReferenceError = class extends RelationshipError {
|
|
1925
|
+
constructor(message) {
|
|
1926
|
+
super(`Circular reference detected: ${message}`);
|
|
1927
|
+
this.name = "CircularReferenceError";
|
|
1908
1928
|
}
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
*/
|
|
1915
|
-
async getActiveTemplates(pageSize = 20, lastDoc) {
|
|
1916
|
-
return this.apiService.getActiveTemplates(pageSize, lastDoc);
|
|
1929
|
+
};
|
|
1930
|
+
var BlockingConditionError = class extends BackofficeError {
|
|
1931
|
+
constructor(message) {
|
|
1932
|
+
super(message);
|
|
1933
|
+
this.name = "BlockingConditionError";
|
|
1917
1934
|
}
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
* @returns Array of templates and the last document for pagination
|
|
1924
|
-
*/
|
|
1925
|
-
async getTemplatesByTags(tags, pageSize = 20, lastDoc) {
|
|
1926
|
-
return this.apiService.getTemplatesByTags(tags, pageSize, lastDoc);
|
|
1935
|
+
};
|
|
1936
|
+
var InvalidBlockingConditionError = class extends BlockingConditionError {
|
|
1937
|
+
constructor(condition) {
|
|
1938
|
+
super(`Neva\u017Ee\u0107i blokiraju\u0107i uslov: ${condition}`);
|
|
1939
|
+
this.name = "InvalidBlockingConditionError";
|
|
1927
1940
|
}
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
* @returns Array of templates and the last document for pagination
|
|
1934
|
-
*/
|
|
1935
|
-
async getTemplatesByCreator(userId, pageSize = 20, lastDoc) {
|
|
1936
|
-
return this.apiService.getTemplatesByCreator(userId, pageSize, lastDoc);
|
|
1941
|
+
};
|
|
1942
|
+
var ContraindicationError = class extends BackofficeError {
|
|
1943
|
+
constructor(message) {
|
|
1944
|
+
super(message);
|
|
1945
|
+
this.name = "ContraindicationError";
|
|
1937
1946
|
}
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
*/
|
|
1944
|
-
async getTemplateVersion(templateId, versionNumber) {
|
|
1945
|
-
return this.apiService.getTemplateVersion(templateId, versionNumber);
|
|
1947
|
+
};
|
|
1948
|
+
var InvalidContraindicationError = class extends ContraindicationError {
|
|
1949
|
+
constructor(contraindication) {
|
|
1950
|
+
super(`Neva\u017Ee\u0107a kontraindikacija: ${contraindication}`);
|
|
1951
|
+
this.name = "InvalidContraindicationError";
|
|
1946
1952
|
}
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1953
|
+
};
|
|
1954
|
+
var TreatmentBenefitError = class extends BackofficeError {
|
|
1955
|
+
constructor(message) {
|
|
1956
|
+
super(message);
|
|
1957
|
+
this.name = "TreatmentBenefitError";
|
|
1958
|
+
}
|
|
1959
|
+
};
|
|
1960
|
+
var InvalidTreatmentBenefitError = class extends TreatmentBenefitError {
|
|
1961
|
+
constructor(benefit) {
|
|
1962
|
+
super(`Neva\u017Ee\u0107i benefit tretmana: ${benefit}`);
|
|
1963
|
+
this.name = "InvalidTreatmentBenefitError";
|
|
1954
1964
|
}
|
|
1955
1965
|
};
|
|
1956
1966
|
export {
|
|
@@ -1966,7 +1976,7 @@ export {
|
|
|
1966
1976
|
CircularReferenceError,
|
|
1967
1977
|
Contraindication,
|
|
1968
1978
|
ContraindicationError,
|
|
1969
|
-
DEFAULT_CERTIFICATION_REQUIREMENT,
|
|
1979
|
+
DEFAULT_CERTIFICATION_REQUIREMENT2 as DEFAULT_CERTIFICATION_REQUIREMENT,
|
|
1970
1980
|
DocumentElementType,
|
|
1971
1981
|
DocumentationTemplateService2 as DocumentationTemplateService,
|
|
1972
1982
|
DynamicVariable,
|