@blackcode_sa/metaestetics-api 1.12.2 → 1.12.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/backoffice/index.d.mts +64 -14
- package/dist/backoffice/index.d.ts +64 -14
- package/dist/backoffice/index.js +72 -53
- package/dist/backoffice/index.mjs +72 -53
- package/dist/index.d.mts +129 -17
- package/dist/index.d.ts +129 -17
- package/dist/index.js +72 -53
- package/dist/index.mjs +72 -53
- package/package.json +1 -1
- package/src/backoffice/services/FIXES_README.md +102 -0
- package/src/backoffice/services/category.service.ts +46 -27
- package/src/backoffice/services/product.service.ts +52 -74
- package/src/backoffice/services/technology.service.ts +99 -116
- package/src/backoffice/types/category.types.ts +28 -2
- package/src/backoffice/types/product.types.ts +10 -9
- package/src/backoffice/types/technology.types.ts +31 -59
|
@@ -15,23 +15,20 @@ import {
|
|
|
15
15
|
arrayUnion,
|
|
16
16
|
arrayRemove,
|
|
17
17
|
Firestore,
|
|
18
|
-
} from
|
|
19
|
-
import { Technology, TECHNOLOGIES_COLLECTION } from
|
|
20
|
-
import { Requirement, RequirementType } from
|
|
21
|
-
import { BlockingCondition } from
|
|
22
|
-
import { ContraindicationDynamic } from
|
|
23
|
-
import { TreatmentBenefitDynamic } from
|
|
18
|
+
} from 'firebase/firestore';
|
|
19
|
+
import { Technology, TECHNOLOGIES_COLLECTION, ITechnologyService } from '../types/technology.types';
|
|
20
|
+
import { Requirement, RequirementType } from '../types/requirement.types';
|
|
21
|
+
import { BlockingCondition } from '../types/static/blocking-condition.types';
|
|
22
|
+
import { ContraindicationDynamic } from '../types/admin-constants.types';
|
|
23
|
+
import { TreatmentBenefitDynamic } from '../types/admin-constants.types';
|
|
24
24
|
import {
|
|
25
25
|
CertificationLevel,
|
|
26
26
|
CertificationSpecialty,
|
|
27
27
|
CertificationRequirement,
|
|
28
|
-
} from
|
|
29
|
-
import { BaseService } from
|
|
30
|
-
import { ProcedureFamily } from
|
|
31
|
-
import {
|
|
32
|
-
Practitioner,
|
|
33
|
-
PractitionerCertification,
|
|
34
|
-
} from "../../types/practitioner";
|
|
28
|
+
} from '../types/static/certification.types';
|
|
29
|
+
import { BaseService } from '../../services/base.service';
|
|
30
|
+
import { ProcedureFamily } from '../types/static/procedure-family.types';
|
|
31
|
+
import { Practitioner, PractitionerCertification } from '../../types/practitioner';
|
|
35
32
|
|
|
36
33
|
/**
|
|
37
34
|
* Default vrednosti za sertifikaciju
|
|
@@ -44,7 +41,7 @@ const DEFAULT_CERTIFICATION_REQUIREMENT: CertificationRequirement = {
|
|
|
44
41
|
/**
|
|
45
42
|
* Service for managing technologies.
|
|
46
43
|
*/
|
|
47
|
-
export class TechnologyService extends BaseService {
|
|
44
|
+
export class TechnologyService extends BaseService implements ITechnologyService {
|
|
48
45
|
/**
|
|
49
46
|
* Reference to the Firestore collection of technologies.
|
|
50
47
|
*/
|
|
@@ -57,10 +54,10 @@ export class TechnologyService extends BaseService {
|
|
|
57
54
|
* @param technology - Data for the new technology.
|
|
58
55
|
* @returns The created technology with its generated ID.
|
|
59
56
|
*/
|
|
60
|
-
async create(technology: Omit<Technology,
|
|
57
|
+
async create(technology: Omit<Technology, 'id' | 'createdAt' | 'updatedAt'>) {
|
|
61
58
|
const now = new Date();
|
|
62
59
|
// Explicitly construct the object to ensure no undefined values are passed.
|
|
63
|
-
const newTechnology: Omit<Technology,
|
|
60
|
+
const newTechnology: Omit<Technology, 'id'> = {
|
|
64
61
|
name: technology.name,
|
|
65
62
|
description: technology.description,
|
|
66
63
|
family: technology.family,
|
|
@@ -71,8 +68,7 @@ export class TechnologyService extends BaseService {
|
|
|
71
68
|
contraindications: technology.contraindications || [],
|
|
72
69
|
benefits: technology.benefits || [],
|
|
73
70
|
certificationRequirement:
|
|
74
|
-
technology.certificationRequirement ||
|
|
75
|
-
DEFAULT_CERTIFICATION_REQUIREMENT,
|
|
71
|
+
technology.certificationRequirement || DEFAULT_CERTIFICATION_REQUIREMENT,
|
|
76
72
|
documentationTemplates: technology.documentationTemplates || [],
|
|
77
73
|
isActive: true,
|
|
78
74
|
createdAt: now,
|
|
@@ -94,10 +90,10 @@ export class TechnologyService extends BaseService {
|
|
|
94
90
|
* @returns A record mapping subcategory ID to technology count.
|
|
95
91
|
*/
|
|
96
92
|
async getTechnologyCounts(active = true) {
|
|
97
|
-
const q = query(this.technologiesRef, where(
|
|
93
|
+
const q = query(this.technologiesRef, where('isActive', '==', active));
|
|
98
94
|
const snapshot = await getDocs(q);
|
|
99
95
|
const counts: Record<string, number> = {};
|
|
100
|
-
snapshot.docs.forEach(
|
|
96
|
+
snapshot.docs.forEach(doc => {
|
|
101
97
|
const tech = doc.data() as Technology;
|
|
102
98
|
counts[tech.subcategoryId] = (counts[tech.subcategoryId] || 0) + 1;
|
|
103
99
|
});
|
|
@@ -110,10 +106,10 @@ export class TechnologyService extends BaseService {
|
|
|
110
106
|
* @returns A record mapping category ID to technology count.
|
|
111
107
|
*/
|
|
112
108
|
async getTechnologyCountsByCategory(active = true) {
|
|
113
|
-
const q = query(this.technologiesRef, where(
|
|
109
|
+
const q = query(this.technologiesRef, where('isActive', '==', active));
|
|
114
110
|
const snapshot = await getDocs(q);
|
|
115
111
|
const counts: Record<string, number> = {};
|
|
116
|
-
snapshot.docs.forEach(
|
|
112
|
+
snapshot.docs.forEach(doc => {
|
|
117
113
|
const tech = doc.data() as Technology;
|
|
118
114
|
counts[tech.categoryId] = (counts[tech.categoryId] || 0) + 1;
|
|
119
115
|
});
|
|
@@ -130,12 +126,12 @@ export class TechnologyService extends BaseService {
|
|
|
130
126
|
active?: boolean;
|
|
131
127
|
limit?: number;
|
|
132
128
|
lastVisible?: DocumentData;
|
|
133
|
-
} = {}
|
|
129
|
+
} = {},
|
|
134
130
|
) {
|
|
135
131
|
const { active = true, limit: queryLimit = 10, lastVisible } = options;
|
|
136
132
|
const constraints = [
|
|
137
|
-
where(
|
|
138
|
-
orderBy(
|
|
133
|
+
where('isActive', '==', active),
|
|
134
|
+
orderBy('name'),
|
|
139
135
|
queryLimit ? limit(queryLimit) : undefined,
|
|
140
136
|
lastVisible ? startAfter(lastVisible) : undefined,
|
|
141
137
|
].filter((c): c is NonNullable<typeof c> => !!c);
|
|
@@ -143,11 +139,11 @@ export class TechnologyService extends BaseService {
|
|
|
143
139
|
const q = query(this.technologiesRef, ...constraints);
|
|
144
140
|
const snapshot = await getDocs(q);
|
|
145
141
|
const technologies = snapshot.docs.map(
|
|
146
|
-
|
|
142
|
+
doc =>
|
|
147
143
|
({
|
|
148
144
|
id: doc.id,
|
|
149
145
|
...doc.data(),
|
|
150
|
-
} as Technology)
|
|
146
|
+
} as Technology),
|
|
151
147
|
);
|
|
152
148
|
const newLastVisible = snapshot.docs[snapshot.docs.length - 1];
|
|
153
149
|
return { technologies, lastVisible: newLastVisible };
|
|
@@ -165,13 +161,13 @@ export class TechnologyService extends BaseService {
|
|
|
165
161
|
active?: boolean;
|
|
166
162
|
limit?: number;
|
|
167
163
|
lastVisible?: DocumentData;
|
|
168
|
-
} = {}
|
|
164
|
+
} = {},
|
|
169
165
|
) {
|
|
170
166
|
const { active = true, limit: queryLimit = 10, lastVisible } = options;
|
|
171
167
|
const constraints = [
|
|
172
|
-
where(
|
|
173
|
-
where(
|
|
174
|
-
orderBy(
|
|
168
|
+
where('categoryId', '==', categoryId),
|
|
169
|
+
where('isActive', '==', active),
|
|
170
|
+
orderBy('name'),
|
|
175
171
|
queryLimit ? limit(queryLimit) : undefined,
|
|
176
172
|
lastVisible ? startAfter(lastVisible) : undefined,
|
|
177
173
|
].filter((c): c is NonNullable<typeof c> => !!c);
|
|
@@ -179,11 +175,11 @@ export class TechnologyService extends BaseService {
|
|
|
179
175
|
const q = query(this.technologiesRef, ...constraints);
|
|
180
176
|
const snapshot = await getDocs(q);
|
|
181
177
|
const technologies = snapshot.docs.map(
|
|
182
|
-
|
|
178
|
+
doc =>
|
|
183
179
|
({
|
|
184
180
|
id: doc.id,
|
|
185
181
|
...doc.data(),
|
|
186
|
-
} as Technology)
|
|
182
|
+
} as Technology),
|
|
187
183
|
);
|
|
188
184
|
const newLastVisible = snapshot.docs[snapshot.docs.length - 1];
|
|
189
185
|
return { technologies, lastVisible: newLastVisible };
|
|
@@ -201,13 +197,13 @@ export class TechnologyService extends BaseService {
|
|
|
201
197
|
active?: boolean;
|
|
202
198
|
limit?: number;
|
|
203
199
|
lastVisible?: DocumentData;
|
|
204
|
-
} = {}
|
|
200
|
+
} = {},
|
|
205
201
|
) {
|
|
206
202
|
const { active = true, limit: queryLimit = 10, lastVisible } = options;
|
|
207
203
|
const constraints = [
|
|
208
|
-
where(
|
|
209
|
-
where(
|
|
210
|
-
orderBy(
|
|
204
|
+
where('subcategoryId', '==', subcategoryId),
|
|
205
|
+
where('isActive', '==', active),
|
|
206
|
+
orderBy('name'),
|
|
211
207
|
queryLimit ? limit(queryLimit) : undefined,
|
|
212
208
|
lastVisible ? startAfter(lastVisible) : undefined,
|
|
213
209
|
].filter((c): c is NonNullable<typeof c> => !!c);
|
|
@@ -215,11 +211,11 @@ export class TechnologyService extends BaseService {
|
|
|
215
211
|
const q = query(this.technologiesRef, ...constraints);
|
|
216
212
|
const snapshot = await getDocs(q);
|
|
217
213
|
const technologies = snapshot.docs.map(
|
|
218
|
-
|
|
214
|
+
doc =>
|
|
219
215
|
({
|
|
220
216
|
id: doc.id,
|
|
221
217
|
...doc.data(),
|
|
222
|
-
} as Technology)
|
|
218
|
+
} as Technology),
|
|
223
219
|
);
|
|
224
220
|
const newLastVisible = snapshot.docs[snapshot.docs.length - 1];
|
|
225
221
|
return { technologies, lastVisible: newLastVisible };
|
|
@@ -231,14 +227,11 @@ export class TechnologyService extends BaseService {
|
|
|
231
227
|
* @param technology - New data for the technology.
|
|
232
228
|
* @returns The updated technology.
|
|
233
229
|
*/
|
|
234
|
-
async update(
|
|
235
|
-
id: string,
|
|
236
|
-
technology: Partial<Omit<Technology, "id" | "createdAt">>
|
|
237
|
-
) {
|
|
230
|
+
async update(id: string, technology: Partial<Omit<Technology, 'id' | 'createdAt'>>) {
|
|
238
231
|
const updateData: { [key: string]: any } = { ...technology };
|
|
239
232
|
|
|
240
233
|
// Remove undefined fields to prevent Firestore errors
|
|
241
|
-
Object.keys(updateData).forEach(
|
|
234
|
+
Object.keys(updateData).forEach(key => {
|
|
242
235
|
if (updateData[key] === undefined) {
|
|
243
236
|
delete updateData[key];
|
|
244
237
|
}
|
|
@@ -291,8 +284,7 @@ export class TechnologyService extends BaseService {
|
|
|
291
284
|
async addRequirement(technologyId: string, requirement: Requirement) {
|
|
292
285
|
const docRef = doc(this.technologiesRef, technologyId);
|
|
293
286
|
|
|
294
|
-
const requirementType =
|
|
295
|
-
requirement.type === "pre" ? "requirements.pre" : "requirements.post";
|
|
287
|
+
const requirementType = requirement.type === 'pre' ? 'requirements.pre' : 'requirements.post';
|
|
296
288
|
|
|
297
289
|
await updateDoc(docRef, {
|
|
298
290
|
[requirementType]: arrayUnion(requirement),
|
|
@@ -311,8 +303,7 @@ export class TechnologyService extends BaseService {
|
|
|
311
303
|
async removeRequirement(technologyId: string, requirement: Requirement) {
|
|
312
304
|
const docRef = doc(this.technologiesRef, technologyId);
|
|
313
305
|
|
|
314
|
-
const requirementType =
|
|
315
|
-
requirement.type === "pre" ? "requirements.pre" : "requirements.post";
|
|
306
|
+
const requirementType = requirement.type === 'pre' ? 'requirements.pre' : 'requirements.post';
|
|
316
307
|
|
|
317
308
|
await updateDoc(docRef, {
|
|
318
309
|
[requirementType]: arrayRemove(requirement),
|
|
@@ -349,7 +340,7 @@ export class TechnologyService extends BaseService {
|
|
|
349
340
|
async updateRequirement(
|
|
350
341
|
technologyId: string,
|
|
351
342
|
oldRequirement: Requirement,
|
|
352
|
-
newRequirement: Requirement
|
|
343
|
+
newRequirement: Requirement,
|
|
353
344
|
) {
|
|
354
345
|
await this.removeRequirement(technologyId, oldRequirement);
|
|
355
346
|
return this.addRequirement(technologyId, newRequirement);
|
|
@@ -361,10 +352,7 @@ export class TechnologyService extends BaseService {
|
|
|
361
352
|
* @param condition - Blokirajući uslov koji se dodaje
|
|
362
353
|
* @returns Ažurirana tehnologija
|
|
363
354
|
*/
|
|
364
|
-
async addBlockingCondition(
|
|
365
|
-
technologyId: string,
|
|
366
|
-
condition: BlockingCondition
|
|
367
|
-
) {
|
|
355
|
+
async addBlockingCondition(technologyId: string, condition: BlockingCondition) {
|
|
368
356
|
const docRef = doc(this.technologiesRef, technologyId);
|
|
369
357
|
|
|
370
358
|
await updateDoc(docRef, {
|
|
@@ -381,10 +369,7 @@ export class TechnologyService extends BaseService {
|
|
|
381
369
|
* @param condition - Blokirajući uslov koji se uklanja
|
|
382
370
|
* @returns Ažurirana tehnologija
|
|
383
371
|
*/
|
|
384
|
-
async removeBlockingCondition(
|
|
385
|
-
technologyId: string,
|
|
386
|
-
condition: BlockingCondition
|
|
387
|
-
) {
|
|
372
|
+
async removeBlockingCondition(technologyId: string, condition: BlockingCondition) {
|
|
388
373
|
const docRef = doc(this.technologiesRef, technologyId);
|
|
389
374
|
|
|
390
375
|
await updateDoc(docRef, {
|
|
@@ -401,10 +386,7 @@ export class TechnologyService extends BaseService {
|
|
|
401
386
|
* @param contraindication - Kontraindikacija koja se dodaje
|
|
402
387
|
* @returns Ažurirana tehnologija
|
|
403
388
|
*/
|
|
404
|
-
async addContraindication(
|
|
405
|
-
technologyId: string,
|
|
406
|
-
contraindication: ContraindicationDynamic
|
|
407
|
-
) {
|
|
389
|
+
async addContraindication(technologyId: string, contraindication: ContraindicationDynamic) {
|
|
408
390
|
const docRef = doc(this.technologiesRef, technologyId);
|
|
409
391
|
const technology = await this.getById(technologyId);
|
|
410
392
|
if (!technology) {
|
|
@@ -412,7 +394,7 @@ export class TechnologyService extends BaseService {
|
|
|
412
394
|
}
|
|
413
395
|
|
|
414
396
|
const existingContraindications = technology.contraindications || [];
|
|
415
|
-
if (existingContraindications.some(
|
|
397
|
+
if (existingContraindications.some(c => c.id === contraindication.id)) {
|
|
416
398
|
return technology; // Already exists, do nothing
|
|
417
399
|
}
|
|
418
400
|
|
|
@@ -430,19 +412,16 @@ export class TechnologyService extends BaseService {
|
|
|
430
412
|
* @param contraindication - Kontraindikacija koja se uklanja
|
|
431
413
|
* @returns Ažurirana tehnologija
|
|
432
414
|
*/
|
|
433
|
-
async removeContraindication(
|
|
434
|
-
technologyId: string,
|
|
435
|
-
contraindication: ContraindicationDynamic
|
|
436
|
-
) {
|
|
415
|
+
async removeContraindication(technologyId: string, contraindication: ContraindicationDynamic) {
|
|
437
416
|
const docRef = doc(this.technologiesRef, technologyId);
|
|
438
417
|
const technology = await this.getById(technologyId);
|
|
439
418
|
if (!technology) {
|
|
440
419
|
throw new Error(`Technology with id ${technologyId} not found`);
|
|
441
420
|
}
|
|
442
421
|
|
|
443
|
-
const updatedContraindications = (
|
|
444
|
-
|
|
445
|
-
)
|
|
422
|
+
const updatedContraindications = (technology.contraindications || []).filter(
|
|
423
|
+
c => c.id !== contraindication.id,
|
|
424
|
+
);
|
|
446
425
|
|
|
447
426
|
await updateDoc(docRef, {
|
|
448
427
|
contraindications: updatedContraindications,
|
|
@@ -459,10 +438,7 @@ export class TechnologyService extends BaseService {
|
|
|
459
438
|
* @param contraindication - The updated contraindication object
|
|
460
439
|
* @returns The updated technology
|
|
461
440
|
*/
|
|
462
|
-
async updateContraindication(
|
|
463
|
-
technologyId: string,
|
|
464
|
-
contraindication: ContraindicationDynamic
|
|
465
|
-
) {
|
|
441
|
+
async updateContraindication(technologyId: string, contraindication: ContraindicationDynamic) {
|
|
466
442
|
const docRef = doc(this.technologiesRef, technologyId);
|
|
467
443
|
const technology = await this.getById(technologyId);
|
|
468
444
|
if (!technology) {
|
|
@@ -470,15 +446,13 @@ export class TechnologyService extends BaseService {
|
|
|
470
446
|
}
|
|
471
447
|
|
|
472
448
|
const contraindications = technology.contraindications || [];
|
|
473
|
-
const index = contraindications.findIndex(
|
|
474
|
-
(c) => c.id === contraindication.id
|
|
475
|
-
);
|
|
449
|
+
const index = contraindications.findIndex(c => c.id === contraindication.id);
|
|
476
450
|
|
|
477
451
|
if (index === -1) {
|
|
478
452
|
// If contraindication doesn't exist, do not update
|
|
479
453
|
// Consider throwing an error if this is an unexpected state
|
|
480
454
|
console.warn(
|
|
481
|
-
`Contraindication with id ${contraindication.id} not found for technology ${technologyId}. No update performed
|
|
455
|
+
`Contraindication with id ${contraindication.id} not found for technology ${technologyId}. No update performed.`,
|
|
482
456
|
);
|
|
483
457
|
return technology;
|
|
484
458
|
}
|
|
@@ -508,7 +482,7 @@ export class TechnologyService extends BaseService {
|
|
|
508
482
|
}
|
|
509
483
|
|
|
510
484
|
const existingBenefits = technology.benefits || [];
|
|
511
|
-
if (existingBenefits.some(
|
|
485
|
+
if (existingBenefits.some(b => b.id === benefit.id)) {
|
|
512
486
|
return technology; // Already exists, do nothing
|
|
513
487
|
}
|
|
514
488
|
|
|
@@ -533,9 +507,7 @@ export class TechnologyService extends BaseService {
|
|
|
533
507
|
throw new Error(`Technology with id ${technologyId} not found`);
|
|
534
508
|
}
|
|
535
509
|
|
|
536
|
-
const updatedBenefits = (technology.benefits || []).filter(
|
|
537
|
-
(b) => b.id !== benefit.id
|
|
538
|
-
);
|
|
510
|
+
const updatedBenefits = (technology.benefits || []).filter(b => b.id !== benefit.id);
|
|
539
511
|
|
|
540
512
|
await updateDoc(docRef, {
|
|
541
513
|
benefits: updatedBenefits,
|
|
@@ -560,12 +532,12 @@ export class TechnologyService extends BaseService {
|
|
|
560
532
|
}
|
|
561
533
|
|
|
562
534
|
const benefits = technology.benefits || [];
|
|
563
|
-
const index = benefits.findIndex(
|
|
535
|
+
const index = benefits.findIndex(b => b.id === benefit.id);
|
|
564
536
|
|
|
565
537
|
if (index === -1) {
|
|
566
538
|
// If benefit doesn't exist, do not update
|
|
567
539
|
console.warn(
|
|
568
|
-
`Benefit with id ${benefit.id} not found for technology ${technologyId}. No update performed
|
|
540
|
+
`Benefit with id ${benefit.id} not found for technology ${technologyId}. No update performed.`,
|
|
569
541
|
);
|
|
570
542
|
return technology;
|
|
571
543
|
}
|
|
@@ -619,7 +591,7 @@ export class TechnologyService extends BaseService {
|
|
|
619
591
|
*/
|
|
620
592
|
async updateCertificationRequirement(
|
|
621
593
|
technologyId: string,
|
|
622
|
-
certificationRequirement: CertificationRequirement
|
|
594
|
+
certificationRequirement: CertificationRequirement,
|
|
623
595
|
) {
|
|
624
596
|
const docRef = doc(this.technologiesRef, technologyId);
|
|
625
597
|
|
|
@@ -637,7 +609,7 @@ export class TechnologyService extends BaseService {
|
|
|
637
609
|
* @returns Zahtevi sertifikacije ili null ako tehnologija ne postoji
|
|
638
610
|
*/
|
|
639
611
|
async getCertificationRequirement(
|
|
640
|
-
technologyId: string
|
|
612
|
+
technologyId: string,
|
|
641
613
|
): Promise<CertificationRequirement | null> {
|
|
642
614
|
const technology = await this.getById(technologyId);
|
|
643
615
|
return technology?.certificationRequirement || null;
|
|
@@ -664,15 +636,13 @@ export class TechnologyService extends BaseService {
|
|
|
664
636
|
*/
|
|
665
637
|
validateCertification(
|
|
666
638
|
requiredCertification: CertificationRequirement,
|
|
667
|
-
practitionerCertification: PractitionerCertification
|
|
639
|
+
practitionerCertification: PractitionerCertification,
|
|
668
640
|
): boolean {
|
|
669
641
|
// Provera nivoa sertifikacije
|
|
670
642
|
// Enum je definisan od najnižeg ka najvišem, pa možemo porediti brojeve
|
|
671
|
-
const doctorLevel = Object.values(CertificationLevel).indexOf(
|
|
672
|
-
practitionerCertification.level
|
|
673
|
-
);
|
|
643
|
+
const doctorLevel = Object.values(CertificationLevel).indexOf(practitionerCertification.level);
|
|
674
644
|
const requiredLevel = Object.values(CertificationLevel).indexOf(
|
|
675
|
-
requiredCertification.minimumLevel
|
|
645
|
+
requiredCertification.minimumLevel,
|
|
676
646
|
);
|
|
677
647
|
|
|
678
648
|
// Doktor mora imati nivo koji je jednak ili viši od zahtevanog
|
|
@@ -683,8 +653,8 @@ export class TechnologyService extends BaseService {
|
|
|
683
653
|
if (requiredSpecialties.length > 0) {
|
|
684
654
|
// Doktor mora imati sve zahtevane specijalizacije
|
|
685
655
|
const doctorSpecialties = practitionerCertification.specialties;
|
|
686
|
-
const hasAllRequiredSpecialties = requiredSpecialties.every(
|
|
687
|
-
|
|
656
|
+
const hasAllRequiredSpecialties = requiredSpecialties.every(requiredSpecialty =>
|
|
657
|
+
doctorSpecialties.includes(requiredSpecialty),
|
|
688
658
|
);
|
|
689
659
|
|
|
690
660
|
if (!hasAllRequiredSpecialties) return false;
|
|
@@ -726,22 +696,14 @@ export class TechnologyService extends BaseService {
|
|
|
726
696
|
const allTechnologies = await this.getAll();
|
|
727
697
|
|
|
728
698
|
// Filter technologies based on certification requirements
|
|
729
|
-
const allowedTechnologies = allTechnologies.technologies.filter(
|
|
730
|
-
(technology)
|
|
731
|
-
this.validateCertification(
|
|
732
|
-
technology.certificationRequirement,
|
|
733
|
-
practitioner.certification
|
|
734
|
-
)
|
|
699
|
+
const allowedTechnologies = allTechnologies.technologies.filter(technology =>
|
|
700
|
+
this.validateCertification(technology.certificationRequirement, practitioner.certification),
|
|
735
701
|
);
|
|
736
702
|
|
|
737
703
|
// Extract unique families, categories, and subcategories
|
|
738
|
-
const families = [...new Set(allowedTechnologies.map(
|
|
739
|
-
const categories = [
|
|
740
|
-
|
|
741
|
-
];
|
|
742
|
-
const subcategories = [
|
|
743
|
-
...new Set(allowedTechnologies.map((t) => t.subcategoryId)),
|
|
744
|
-
];
|
|
704
|
+
const families = [...new Set(allowedTechnologies.map(t => t.family))];
|
|
705
|
+
const categories = [...new Set(allowedTechnologies.map(t => t.categoryId))];
|
|
706
|
+
const subcategories = [...new Set(allowedTechnologies.map(t => t.subcategoryId))];
|
|
745
707
|
|
|
746
708
|
return {
|
|
747
709
|
technologies: allowedTechnologies,
|
|
@@ -751,6 +713,27 @@ export class TechnologyService extends BaseService {
|
|
|
751
713
|
};
|
|
752
714
|
}
|
|
753
715
|
|
|
716
|
+
/**
|
|
717
|
+
* Gets all active technologies for a subcategory for filter dropdowns (by subcategory only).
|
|
718
|
+
* @param subcategoryId - The ID of the subcategory.
|
|
719
|
+
*/
|
|
720
|
+
async getAllForFilterBySubcategory(subcategoryId: string): Promise<Technology[]> {
|
|
721
|
+
const q = query(
|
|
722
|
+
collection(this.db, TECHNOLOGIES_COLLECTION),
|
|
723
|
+
where('isActive', '==', true),
|
|
724
|
+
where('subcategoryId', '==', subcategoryId),
|
|
725
|
+
orderBy('name'),
|
|
726
|
+
);
|
|
727
|
+
const snapshot = await getDocs(q);
|
|
728
|
+
return snapshot.docs.map(
|
|
729
|
+
doc =>
|
|
730
|
+
({
|
|
731
|
+
id: doc.id,
|
|
732
|
+
...doc.data(),
|
|
733
|
+
} as Technology),
|
|
734
|
+
);
|
|
735
|
+
}
|
|
736
|
+
|
|
754
737
|
/**
|
|
755
738
|
* Gets all active technologies for a subcategory for filter dropdowns.
|
|
756
739
|
* @param categoryId - The ID of the parent category.
|
|
@@ -758,22 +741,22 @@ export class TechnologyService extends BaseService {
|
|
|
758
741
|
*/
|
|
759
742
|
async getAllForFilterBySubcategoryId(
|
|
760
743
|
categoryId: string,
|
|
761
|
-
subcategoryId: string
|
|
744
|
+
subcategoryId: string,
|
|
762
745
|
): Promise<Technology[]> {
|
|
763
746
|
const q = query(
|
|
764
747
|
collection(this.db, TECHNOLOGIES_COLLECTION),
|
|
765
|
-
where(
|
|
766
|
-
where(
|
|
767
|
-
where(
|
|
768
|
-
orderBy(
|
|
748
|
+
where('isActive', '==', true),
|
|
749
|
+
where('categoryId', '==', categoryId),
|
|
750
|
+
where('subcategoryId', '==', subcategoryId),
|
|
751
|
+
orderBy('name'),
|
|
769
752
|
);
|
|
770
753
|
const snapshot = await getDocs(q);
|
|
771
754
|
return snapshot.docs.map(
|
|
772
|
-
|
|
755
|
+
doc =>
|
|
773
756
|
({
|
|
774
757
|
id: doc.id,
|
|
775
758
|
...doc.data(),
|
|
776
|
-
} as Technology)
|
|
759
|
+
} as Technology),
|
|
777
760
|
);
|
|
778
761
|
}
|
|
779
762
|
|
|
@@ -783,16 +766,16 @@ export class TechnologyService extends BaseService {
|
|
|
783
766
|
async getAllForFilter(): Promise<Technology[]> {
|
|
784
767
|
const q = query(
|
|
785
768
|
collection(this.db, TECHNOLOGIES_COLLECTION),
|
|
786
|
-
where(
|
|
787
|
-
orderBy(
|
|
769
|
+
where('isActive', '==', true),
|
|
770
|
+
orderBy('name'),
|
|
788
771
|
);
|
|
789
772
|
const snapshot = await getDocs(q);
|
|
790
773
|
return snapshot.docs.map(
|
|
791
|
-
|
|
774
|
+
doc =>
|
|
792
775
|
({
|
|
793
776
|
id: doc.id,
|
|
794
777
|
...doc.data(),
|
|
795
|
-
} as Technology)
|
|
778
|
+
} as Technology),
|
|
796
779
|
);
|
|
797
780
|
}
|
|
798
781
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ProcedureFamily } from
|
|
1
|
+
import { ProcedureFamily } from './static/procedure-family.types';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Kategorija procedura
|
|
@@ -33,4 +33,30 @@ export interface Category {
|
|
|
33
33
|
/**
|
|
34
34
|
* Kolekcija u Firestore bazi gde se čuvaju kategorije
|
|
35
35
|
*/
|
|
36
|
-
export const CATEGORIES_COLLECTION =
|
|
36
|
+
export const CATEGORIES_COLLECTION = 'backoffice_categories';
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Interface for the CategoryService class
|
|
40
|
+
*/
|
|
41
|
+
export interface ICategoryService {
|
|
42
|
+
create(category: Omit<Category, 'id' | 'createdAt' | 'updatedAt'>): Promise<Category>;
|
|
43
|
+
getCategoryCounts(active?: boolean): Promise<Record<string, number>>;
|
|
44
|
+
getAllForFilter(): Promise<Category[]>;
|
|
45
|
+
getAllForFilterByFamily(family: ProcedureFamily): Promise<Category[]>;
|
|
46
|
+
getAll(options?: {
|
|
47
|
+
active?: boolean;
|
|
48
|
+
limit?: number;
|
|
49
|
+
lastVisible?: any;
|
|
50
|
+
}): Promise<{ categories: Category[]; lastVisible: any }>;
|
|
51
|
+
getAllByFamily(
|
|
52
|
+
family: ProcedureFamily,
|
|
53
|
+
options?: { active?: boolean; limit?: number; lastVisible?: any },
|
|
54
|
+
): Promise<{ categories: Category[]; lastVisible: any }>;
|
|
55
|
+
update(
|
|
56
|
+
id: string,
|
|
57
|
+
category: Partial<Omit<Category, 'id' | 'createdAt'>>,
|
|
58
|
+
): Promise<Category | null>;
|
|
59
|
+
delete(id: string): Promise<void>;
|
|
60
|
+
reactivate(id: string): Promise<void>;
|
|
61
|
+
getById(id: string): Promise<Category | null>;
|
|
62
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ContraindicationDynamic } from
|
|
1
|
+
import type { ContraindicationDynamic } from './admin-constants.types';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Product used in procedures
|
|
@@ -43,7 +43,7 @@ export interface Product {
|
|
|
43
43
|
/**
|
|
44
44
|
* Collection in Firestore database where products are stored
|
|
45
45
|
*/
|
|
46
|
-
export const PRODUCTS_COLLECTION =
|
|
46
|
+
export const PRODUCTS_COLLECTION = 'products';
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
49
|
* Interface for the ProductService class
|
|
@@ -58,10 +58,7 @@ export interface IProductService {
|
|
|
58
58
|
create(
|
|
59
59
|
technologyId: string,
|
|
60
60
|
brandId: string,
|
|
61
|
-
product: Omit<
|
|
62
|
-
Product,
|
|
63
|
-
"id" | "createdAt" | "updatedAt" | "brandId" | "technologyId"
|
|
64
|
-
>
|
|
61
|
+
product: Omit<Product, 'id' | 'createdAt' | 'updatedAt' | 'brandId' | 'technologyId'>,
|
|
65
62
|
): Promise<Product>;
|
|
66
63
|
|
|
67
64
|
/**
|
|
@@ -93,6 +90,12 @@ export interface IProductService {
|
|
|
93
90
|
byTechnology: Record<string, number>;
|
|
94
91
|
}>;
|
|
95
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Gets all products for a specific technology (non-paginated, for filters/dropdowns)
|
|
95
|
+
* @param technologyId - ID of the technology
|
|
96
|
+
*/
|
|
97
|
+
getAllByTechnology(technologyId: string): Promise<Product[]>;
|
|
98
|
+
|
|
96
99
|
/**
|
|
97
100
|
* Gets all products for a brand
|
|
98
101
|
* @param brandId - ID of the brand
|
|
@@ -108,9 +111,7 @@ export interface IProductService {
|
|
|
108
111
|
update(
|
|
109
112
|
technologyId: string,
|
|
110
113
|
productId: string,
|
|
111
|
-
product: Partial<
|
|
112
|
-
Omit<Product, "id" | "createdAt" | "brandId" | "technologyId">
|
|
113
|
-
>
|
|
114
|
+
product: Partial<Omit<Product, 'id' | 'createdAt' | 'brandId' | 'technologyId'>>,
|
|
114
115
|
): Promise<Product | null>;
|
|
115
116
|
|
|
116
117
|
/**
|