@blackcode_sa/metaestetics-api 1.13.5 → 1.13.8
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 +20 -1
- package/dist/admin/index.d.ts +20 -1
- package/dist/admin/index.js +217 -1
- package/dist/admin/index.mjs +217 -1
- package/dist/index.d.mts +26 -3
- package/dist/index.d.ts +26 -3
- package/dist/index.js +168 -6
- package/dist/index.mjs +168 -6
- package/package.json +121 -121
- package/src/__mocks__/firstore.ts +10 -10
- package/src/admin/aggregation/README.md +79 -79
- package/src/admin/aggregation/appointment/README.md +128 -128
- package/src/admin/aggregation/appointment/appointment.aggregation.service.ts +1984 -1984
- package/src/admin/aggregation/appointment/index.ts +1 -1
- package/src/admin/aggregation/clinic/README.md +52 -52
- package/src/admin/aggregation/clinic/clinic.aggregation.service.ts +966 -703
- package/src/admin/aggregation/clinic/index.ts +1 -1
- package/src/admin/aggregation/forms/README.md +13 -13
- package/src/admin/aggregation/forms/filled-forms.aggregation.service.ts +322 -322
- package/src/admin/aggregation/forms/index.ts +1 -1
- package/src/admin/aggregation/index.ts +8 -8
- package/src/admin/aggregation/patient/README.md +27 -27
- package/src/admin/aggregation/patient/index.ts +1 -1
- package/src/admin/aggregation/patient/patient.aggregation.service.ts +141 -141
- package/src/admin/aggregation/practitioner/README.md +42 -42
- package/src/admin/aggregation/practitioner/index.ts +1 -1
- package/src/admin/aggregation/practitioner/practitioner.aggregation.service.ts +433 -433
- package/src/admin/aggregation/practitioner-invite/index.ts +1 -1
- package/src/admin/aggregation/practitioner-invite/practitioner-invite.aggregation.service.ts +961 -961
- package/src/admin/aggregation/procedure/README.md +43 -43
- package/src/admin/aggregation/procedure/index.ts +1 -1
- package/src/admin/aggregation/procedure/procedure.aggregation.service.ts +702 -702
- package/src/admin/aggregation/reviews/index.ts +1 -1
- package/src/admin/aggregation/reviews/reviews.aggregation.service.ts +689 -689
- package/src/admin/analytics/analytics.admin.service.ts +278 -278
- package/src/admin/analytics/index.ts +2 -2
- package/src/admin/booking/README.md +125 -125
- package/src/admin/booking/booking.admin.ts +1037 -1037
- package/src/admin/booking/booking.calculator.ts +712 -712
- package/src/admin/booking/booking.types.ts +59 -59
- package/src/admin/booking/index.ts +3 -3
- package/src/admin/booking/timezones-problem.md +185 -185
- package/src/admin/calendar/README.md +7 -7
- package/src/admin/calendar/calendar.admin.service.ts +345 -345
- package/src/admin/calendar/index.ts +1 -1
- package/src/admin/documentation-templates/document-manager.admin.ts +260 -260
- package/src/admin/documentation-templates/index.ts +1 -1
- package/src/admin/free-consultation/free-consultation-utils.admin.ts +148 -148
- package/src/admin/free-consultation/index.ts +1 -1
- package/src/admin/index.ts +81 -81
- package/src/admin/logger/index.ts +78 -78
- package/src/admin/mailing/README.md +95 -95
- package/src/admin/mailing/appointment/appointment.mailing.service.ts +732 -732
- package/src/admin/mailing/appointment/index.ts +1 -1
- package/src/admin/mailing/appointment/templates/patient/appointment-confirmed.html +40 -40
- package/src/admin/mailing/base.mailing.service.ts +208 -208
- package/src/admin/mailing/index.ts +3 -3
- package/src/admin/mailing/practitionerInvite/existing-practitioner-invite.mailing.ts +611 -611
- package/src/admin/mailing/practitionerInvite/index.ts +2 -2
- package/src/admin/mailing/practitionerInvite/practitionerInvite.mailing.ts +395 -395
- package/src/admin/mailing/practitionerInvite/templates/existing-practitioner-invitation.template.ts +155 -155
- package/src/admin/mailing/practitionerInvite/templates/invitation.template.ts +101 -101
- package/src/admin/mailing/practitionerInvite/templates/invite-accepted-notification.template.ts +228 -228
- package/src/admin/mailing/practitionerInvite/templates/invite-rejected-notification.template.ts +242 -242
- package/src/admin/notifications/index.ts +1 -1
- package/src/admin/notifications/notifications.admin.ts +710 -710
- package/src/admin/requirements/README.md +128 -128
- package/src/admin/requirements/index.ts +1 -1
- package/src/admin/requirements/patient-requirements.admin.service.ts +475 -475
- package/src/admin/users/index.ts +1 -1
- package/src/admin/users/user-profile.admin.ts +405 -405
- package/src/backoffice/constants/certification.constants.ts +13 -13
- package/src/backoffice/constants/index.ts +1 -1
- package/src/backoffice/errors/backoffice.errors.ts +181 -181
- package/src/backoffice/errors/index.ts +1 -1
- package/src/backoffice/expo-safe/README.md +26 -26
- package/src/backoffice/expo-safe/index.ts +41 -41
- package/src/backoffice/index.ts +5 -5
- package/src/backoffice/services/FIXES_README.md +102 -102
- package/src/backoffice/services/README.md +57 -57
- package/src/backoffice/services/analytics.service.proposal.md +863 -863
- package/src/backoffice/services/analytics.service.summary.md +143 -143
- package/src/backoffice/services/brand.service.ts +256 -256
- package/src/backoffice/services/category.service.ts +384 -384
- package/src/backoffice/services/constants.service.ts +385 -385
- package/src/backoffice/services/documentation-template.service.ts +202 -202
- package/src/backoffice/services/index.ts +10 -10
- package/src/backoffice/services/migrate-products.ts +116 -116
- package/src/backoffice/services/product.service.ts +553 -553
- package/src/backoffice/services/requirement.service.ts +235 -235
- package/src/backoffice/services/subcategory.service.ts +461 -461
- package/src/backoffice/services/technology.service.ts +1151 -1151
- package/src/backoffice/types/README.md +12 -12
- package/src/backoffice/types/admin-constants.types.ts +69 -69
- package/src/backoffice/types/brand.types.ts +29 -29
- package/src/backoffice/types/category.types.ts +67 -67
- package/src/backoffice/types/documentation-templates.types.ts +28 -28
- package/src/backoffice/types/index.ts +10 -10
- package/src/backoffice/types/procedure-product.types.ts +38 -38
- package/src/backoffice/types/product.types.ts +240 -240
- package/src/backoffice/types/requirement.types.ts +63 -63
- package/src/backoffice/types/static/README.md +18 -18
- package/src/backoffice/types/static/blocking-condition.types.ts +21 -21
- package/src/backoffice/types/static/certification.types.ts +37 -37
- package/src/backoffice/types/static/contraindication.types.ts +19 -19
- package/src/backoffice/types/static/index.ts +6 -6
- package/src/backoffice/types/static/pricing.types.ts +16 -16
- package/src/backoffice/types/static/procedure-family.types.ts +14 -14
- package/src/backoffice/types/static/treatment-benefit.types.ts +22 -22
- package/src/backoffice/types/subcategory.types.ts +34 -34
- package/src/backoffice/types/technology.types.ts +168 -168
- package/src/backoffice/validations/index.ts +1 -1
- package/src/backoffice/validations/schemas.ts +164 -164
- package/src/config/__mocks__/firebase.ts +99 -99
- package/src/config/firebase.ts +78 -78
- package/src/config/index.ts +9 -9
- package/src/errors/auth.error.ts +6 -6
- package/src/errors/auth.errors.ts +211 -200
- package/src/errors/clinic.errors.ts +32 -32
- package/src/errors/firebase.errors.ts +47 -47
- package/src/errors/user.errors.ts +99 -99
- package/src/index.backup.ts +407 -407
- package/src/index.ts +6 -6
- package/src/locales/en.ts +31 -31
- package/src/recommender/admin/index.ts +1 -1
- package/src/recommender/admin/services/recommender.service.admin.ts +5 -5
- package/src/recommender/front/index.ts +1 -1
- package/src/recommender/front/services/onboarding.service.ts +5 -5
- package/src/recommender/front/services/recommender.service.ts +3 -3
- package/src/recommender/index.ts +1 -1
- package/src/services/PATIENTAUTH.MD +197 -197
- package/src/services/README.md +106 -106
- package/src/services/__tests__/auth/auth.mock.test.ts +17 -17
- package/src/services/__tests__/auth/auth.setup.ts +293 -293
- package/src/services/__tests__/auth.service.test.ts +346 -346
- package/src/services/__tests__/base.service.test.ts +77 -77
- package/src/services/__tests__/user.service.test.ts +528 -528
- package/src/services/analytics/ARCHITECTURE.md +199 -199
- package/src/services/analytics/CLOUD_FUNCTIONS.md +225 -225
- package/src/services/analytics/GROUPED_ANALYTICS.md +501 -501
- package/src/services/analytics/QUICK_START.md +393 -393
- package/src/services/analytics/README.md +304 -304
- package/src/services/analytics/SUMMARY.md +141 -141
- package/src/services/analytics/TRENDS.md +380 -380
- package/src/services/analytics/USAGE_GUIDE.md +518 -518
- package/src/services/analytics/analytics-cloud.service.ts +222 -222
- package/src/services/analytics/analytics.service.ts +2142 -2142
- package/src/services/analytics/index.ts +4 -4
- package/src/services/analytics/review-analytics.service.ts +941 -941
- package/src/services/analytics/utils/appointment-filtering.utils.ts +138 -138
- package/src/services/analytics/utils/cost-calculation.utils.ts +182 -182
- package/src/services/analytics/utils/grouping.utils.ts +434 -434
- package/src/services/analytics/utils/stored-analytics.utils.ts +347 -347
- package/src/services/analytics/utils/time-calculation.utils.ts +186 -186
- package/src/services/analytics/utils/trend-calculation.utils.ts +200 -200
- package/src/services/appointment/README.md +17 -17
- package/src/services/appointment/appointment.service.ts +2558 -2558
- package/src/services/appointment/index.ts +1 -1
- package/src/services/appointment/utils/appointment.utils.ts +552 -552
- package/src/services/appointment/utils/extended-procedure.utils.ts +314 -314
- package/src/services/appointment/utils/form-initialization.utils.ts +225 -225
- package/src/services/appointment/utils/recommended-procedure.utils.ts +195 -195
- package/src/services/appointment/utils/zone-management.utils.ts +353 -353
- package/src/services/appointment/utils/zone-photo.utils.ts +152 -152
- package/src/services/auth/auth.service.ts +1043 -989
- package/src/services/auth/auth.v2.service.ts +961 -961
- package/src/services/auth/index.ts +7 -7
- package/src/services/auth/utils/error.utils.ts +90 -90
- package/src/services/auth/utils/firebase.utils.ts +49 -49
- package/src/services/auth/utils/index.ts +21 -21
- package/src/services/auth/utils/practitioner.utils.ts +125 -125
- package/src/services/base.service.ts +41 -41
- package/src/services/calendar/calendar.service.ts +1077 -1077
- package/src/services/calendar/calendar.v2.service.ts +1683 -1683
- package/src/services/calendar/calendar.v3.service.ts +313 -313
- package/src/services/calendar/externalCalendar.service.ts +178 -178
- package/src/services/calendar/index.ts +5 -5
- package/src/services/calendar/synced-calendars.service.ts +743 -743
- package/src/services/calendar/utils/appointment.utils.ts +265 -265
- package/src/services/calendar/utils/calendar-event.utils.ts +646 -646
- package/src/services/calendar/utils/clinic.utils.ts +237 -237
- package/src/services/calendar/utils/docs.utils.ts +157 -157
- package/src/services/calendar/utils/google-calendar.utils.ts +697 -697
- package/src/services/calendar/utils/index.ts +8 -8
- package/src/services/calendar/utils/patient.utils.ts +198 -198
- package/src/services/calendar/utils/practitioner.utils.ts +221 -221
- package/src/services/calendar/utils/synced-calendar.utils.ts +472 -472
- package/src/services/clinic/README.md +204 -204
- package/src/services/clinic/__tests__/clinic-admin.service.test.ts +287 -287
- package/src/services/clinic/__tests__/clinic-group.service.test.ts +352 -352
- package/src/services/clinic/__tests__/clinic.service.test.ts +354 -354
- package/src/services/clinic/billing-transactions.service.ts +217 -217
- package/src/services/clinic/clinic-admin.service.ts +202 -202
- package/src/services/clinic/clinic-group.service.ts +310 -310
- package/src/services/clinic/clinic.service.ts +708 -708
- package/src/services/clinic/index.ts +5 -5
- package/src/services/clinic/practitioner-invite.service.ts +519 -519
- package/src/services/clinic/utils/admin.utils.ts +551 -551
- package/src/services/clinic/utils/clinic-group.utils.ts +646 -646
- package/src/services/clinic/utils/clinic.utils.ts +949 -949
- package/src/services/clinic/utils/filter.utils.d.ts +23 -23
- package/src/services/clinic/utils/filter.utils.ts +446 -446
- package/src/services/clinic/utils/index.ts +11 -11
- package/src/services/clinic/utils/photos.utils.ts +188 -188
- package/src/services/clinic/utils/search.utils.ts +84 -84
- package/src/services/clinic/utils/tag.utils.ts +124 -124
- package/src/services/documentation-templates/documentation-template.service.ts +537 -537
- package/src/services/documentation-templates/filled-document.service.ts +587 -587
- package/src/services/documentation-templates/index.ts +2 -2
- package/src/services/index.ts +14 -14
- package/src/services/media/index.ts +1 -1
- package/src/services/media/media.service.ts +418 -418
- package/src/services/notifications/__tests__/notification.service.test.ts +242 -242
- package/src/services/notifications/index.ts +1 -1
- package/src/services/notifications/notification.service.ts +215 -215
- package/src/services/patient/README.md +48 -48
- package/src/services/patient/To-Do.md +43 -43
- package/src/services/patient/__tests__/patient.service.test.ts +294 -294
- package/src/services/patient/index.ts +2 -2
- package/src/services/patient/patient.service.ts +883 -883
- package/src/services/patient/patientRequirements.service.ts +285 -285
- package/src/services/patient/utils/aesthetic-analysis.utils.ts +176 -176
- package/src/services/patient/utils/clinic.utils.ts +80 -80
- package/src/services/patient/utils/docs.utils.ts +142 -142
- package/src/services/patient/utils/index.ts +9 -9
- package/src/services/patient/utils/location.utils.ts +126 -126
- package/src/services/patient/utils/medical-stuff.utils.ts +143 -143
- package/src/services/patient/utils/medical.utils.ts +458 -458
- package/src/services/patient/utils/practitioner.utils.ts +260 -260
- package/src/services/patient/utils/profile.utils.ts +510 -510
- package/src/services/patient/utils/sensitive.utils.ts +260 -260
- package/src/services/patient/utils/token.utils.ts +211 -211
- package/src/services/practitioner/README.md +145 -145
- package/src/services/practitioner/index.ts +1 -1
- package/src/services/practitioner/practitioner.service.ts +1799 -1742
- package/src/services/procedure/README.md +163 -163
- package/src/services/procedure/index.ts +1 -1
- package/src/services/procedure/procedure.service.ts +2307 -2200
- package/src/services/reviews/index.ts +1 -1
- package/src/services/reviews/reviews.service.ts +734 -734
- package/src/services/user/index.ts +1 -1
- package/src/services/user/user.service.ts +489 -489
- package/src/services/user/user.v2.service.ts +466 -466
- package/src/types/analytics/analytics.types.ts +597 -597
- package/src/types/analytics/grouped-analytics.types.ts +173 -173
- package/src/types/analytics/index.ts +4 -4
- package/src/types/analytics/stored-analytics.types.ts +137 -137
- package/src/types/appointment/index.ts +480 -480
- package/src/types/calendar/index.ts +258 -258
- package/src/types/calendar/synced-calendar.types.ts +66 -66
- package/src/types/clinic/index.ts +498 -498
- package/src/types/clinic/practitioner-invite.types.ts +91 -91
- package/src/types/clinic/preferences.types.ts +159 -159
- package/src/types/clinic/to-do +3 -3
- package/src/types/documentation-templates/index.ts +308 -308
- package/src/types/index.ts +47 -47
- package/src/types/notifications/README.md +77 -77
- package/src/types/notifications/index.ts +286 -286
- package/src/types/patient/aesthetic-analysis.types.ts +66 -66
- package/src/types/patient/allergies.ts +58 -58
- package/src/types/patient/index.ts +275 -275
- package/src/types/patient/medical-info.types.ts +152 -152
- package/src/types/patient/patient-requirements.ts +92 -92
- package/src/types/patient/token.types.ts +61 -61
- package/src/types/practitioner/index.ts +206 -206
- package/src/types/procedure/index.ts +181 -181
- package/src/types/profile/index.ts +39 -39
- package/src/types/reviews/index.ts +132 -132
- package/src/types/tz-lookup.d.ts +4 -4
- package/src/types/user/index.ts +38 -38
- package/src/utils/TIMESTAMPS.md +176 -176
- package/src/utils/TimestampUtils.ts +241 -241
- package/src/utils/index.ts +1 -1
- package/src/validations/appointment.schema.ts +574 -574
- package/src/validations/calendar.schema.ts +225 -225
- package/src/validations/clinic.schema.ts +494 -494
- package/src/validations/common.schema.ts +25 -25
- package/src/validations/documentation-templates/index.ts +1 -1
- package/src/validations/documentation-templates/template.schema.ts +220 -220
- package/src/validations/documentation-templates.schema.ts +10 -10
- package/src/validations/index.ts +20 -20
- package/src/validations/media.schema.ts +10 -10
- package/src/validations/notification.schema.ts +90 -90
- package/src/validations/patient/aesthetic-analysis.schema.ts +55 -55
- package/src/validations/patient/medical-info.schema.ts +125 -125
- package/src/validations/patient/patient-requirements.schema.ts +84 -84
- package/src/validations/patient/token.schema.ts +29 -29
- package/src/validations/patient.schema.ts +217 -217
- package/src/validations/practitioner.schema.ts +222 -222
- package/src/validations/procedure-product.schema.ts +41 -41
- package/src/validations/procedure.schema.ts +124 -124
- package/src/validations/profile-info.schema.ts +41 -41
- package/src/validations/reviews.schema.ts +195 -195
- package/src/validations/schemas.ts +104 -104
- package/src/validations/shared.schema.ts +78 -78
|
@@ -1,235 +1,235 @@
|
|
|
1
|
-
import {
|
|
2
|
-
addDoc,
|
|
3
|
-
collection,
|
|
4
|
-
doc,
|
|
5
|
-
getDoc,
|
|
6
|
-
getDocs,
|
|
7
|
-
query,
|
|
8
|
-
updateDoc,
|
|
9
|
-
where,
|
|
10
|
-
orderBy,
|
|
11
|
-
} from "firebase/firestore";
|
|
12
|
-
import {
|
|
13
|
-
Requirement,
|
|
14
|
-
RequirementType,
|
|
15
|
-
REQUIREMENTS_COLLECTION,
|
|
16
|
-
} from "../types/requirement.types";
|
|
17
|
-
import { BaseService } from "../../services/base.service";
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Servis za upravljanje globalnim zahtevima.
|
|
21
|
-
* Zahtevi se mogu kreirati globalno i zatim povezati sa različitim tehnologijama.
|
|
22
|
-
* Ovo omogućava ponovno korišćenje istih zahteva za različite tehnologije.
|
|
23
|
-
*
|
|
24
|
-
* @example
|
|
25
|
-
* const requirementService = new RequirementService();
|
|
26
|
-
*
|
|
27
|
-
* // Kreiranje globalnog zahteva
|
|
28
|
-
* const requirement = await requirementService.create({
|
|
29
|
-
* type: "pre",
|
|
30
|
-
* name: "Stay Hydrated",
|
|
31
|
-
* description: "Drink plenty of water",
|
|
32
|
-
* timeframe: {
|
|
33
|
-
* duration: 2,
|
|
34
|
-
* unit: "hours",
|
|
35
|
-
* notifyAt: [2, 1]
|
|
36
|
-
* },
|
|
37
|
-
* importance: "high"
|
|
38
|
-
* });
|
|
39
|
-
*/
|
|
40
|
-
export class RequirementService extends BaseService {
|
|
41
|
-
/**
|
|
42
|
-
* Referenca na Firestore kolekciju zahteva
|
|
43
|
-
*/
|
|
44
|
-
private get requirementsRef() {
|
|
45
|
-
return collection(this.db, REQUIREMENTS_COLLECTION);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Kreira novi globalni zahtev
|
|
50
|
-
* @param requirement - Podaci za novi zahtev
|
|
51
|
-
* @returns Kreirani zahtev sa generisanim ID-em
|
|
52
|
-
*/
|
|
53
|
-
async create(
|
|
54
|
-
requirement: Omit<Requirement, "id" | "createdAt" | "updatedAt">
|
|
55
|
-
) {
|
|
56
|
-
const now = new Date();
|
|
57
|
-
const newRequirement: Omit<Requirement, "id"> = {
|
|
58
|
-
...requirement,
|
|
59
|
-
createdAt: now,
|
|
60
|
-
updatedAt: now,
|
|
61
|
-
isActive: true,
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
const docRef = await addDoc(this.requirementsRef, newRequirement);
|
|
65
|
-
return { id: docRef.id, ...newRequirement };
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Vraća sve aktivne zahteve
|
|
70
|
-
* @returns Lista aktivnih zahteva
|
|
71
|
-
*/
|
|
72
|
-
async getAll() {
|
|
73
|
-
const q = query(this.requirementsRef, where("isActive", "==", true));
|
|
74
|
-
const snapshot = await getDocs(q);
|
|
75
|
-
return snapshot.docs.map(
|
|
76
|
-
(doc) =>
|
|
77
|
-
({
|
|
78
|
-
id: doc.id,
|
|
79
|
-
...doc.data(),
|
|
80
|
-
} as Requirement)
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Vraća sve aktivne zahteve određenog tipa
|
|
86
|
-
* @param type - Tip zahteva (pre/post)
|
|
87
|
-
* @returns Lista zahteva određenog tipa
|
|
88
|
-
*/
|
|
89
|
-
async getAllByType(type: RequirementType) {
|
|
90
|
-
const q = query(
|
|
91
|
-
this.requirementsRef,
|
|
92
|
-
where("type", "==", type),
|
|
93
|
-
where("isActive", "==", true)
|
|
94
|
-
);
|
|
95
|
-
const snapshot = await getDocs(q);
|
|
96
|
-
return snapshot.docs.map(
|
|
97
|
-
(doc) =>
|
|
98
|
-
({
|
|
99
|
-
id: doc.id,
|
|
100
|
-
...doc.data(),
|
|
101
|
-
} as Requirement)
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Searches for requirements by name.
|
|
107
|
-
* @param name - The name to search for.
|
|
108
|
-
* @param type - The type of requirement (pre/post).
|
|
109
|
-
* @returns A list of requirements that match the search criteria.
|
|
110
|
-
*/
|
|
111
|
-
async search(name: string, type: RequirementType) {
|
|
112
|
-
const requirements = await this.getAllByType(type);
|
|
113
|
-
return requirements.filter((r) =>
|
|
114
|
-
r.name.toLowerCase().includes(name.toLowerCase())
|
|
115
|
-
);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Ažurira postojeći zahtev
|
|
120
|
-
* @param id - ID zahteva koji se ažurira
|
|
121
|
-
* @param requirement - Novi podaci za zahtev
|
|
122
|
-
* @returns Ažurirani zahtev
|
|
123
|
-
*/
|
|
124
|
-
async update(
|
|
125
|
-
id: string,
|
|
126
|
-
requirement: Partial<Omit<Requirement, "id" | "createdAt">>
|
|
127
|
-
) {
|
|
128
|
-
const updateData = {
|
|
129
|
-
...requirement,
|
|
130
|
-
updatedAt: new Date(),
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
const docRef = doc(this.requirementsRef, id);
|
|
134
|
-
await updateDoc(docRef, updateData);
|
|
135
|
-
return this.getById(id);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Soft delete zahteva (postavlja isActive na false)
|
|
140
|
-
* @param id - ID zahteva koji se briše
|
|
141
|
-
*/
|
|
142
|
-
async delete(id: string) {
|
|
143
|
-
await this.update(id, { isActive: false });
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Vraća zahtev po ID-u
|
|
148
|
-
* @param id - ID traženog zahteva
|
|
149
|
-
* @returns Zahtev ili null ako ne postoji
|
|
150
|
-
*/
|
|
151
|
-
async getById(id: string) {
|
|
152
|
-
const docRef = doc(this.requirementsRef, id);
|
|
153
|
-
const docSnap = await getDoc(docRef);
|
|
154
|
-
if (!docSnap.exists()) return null;
|
|
155
|
-
return {
|
|
156
|
-
id: docSnap.id,
|
|
157
|
-
...docSnap.data(),
|
|
158
|
-
} as Requirement;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Exports requirements to CSV string, suitable for Excel/Sheets.
|
|
163
|
-
* Includes headers and optional UTF-8 BOM.
|
|
164
|
-
* By default exports only active requirements (set includeInactive to true to export all).
|
|
165
|
-
*/
|
|
166
|
-
async exportToCsv(options?: {
|
|
167
|
-
includeInactive?: boolean;
|
|
168
|
-
includeBom?: boolean;
|
|
169
|
-
}): Promise<string> {
|
|
170
|
-
const includeInactive = options?.includeInactive ?? false;
|
|
171
|
-
const includeBom = options?.includeBom ?? true;
|
|
172
|
-
|
|
173
|
-
const headers = [
|
|
174
|
-
"id",
|
|
175
|
-
"type",
|
|
176
|
-
"name",
|
|
177
|
-
"description",
|
|
178
|
-
"timeframe_duration",
|
|
179
|
-
"timeframe_unit",
|
|
180
|
-
"timeframe_notifyAt",
|
|
181
|
-
"importance",
|
|
182
|
-
"isActive",
|
|
183
|
-
];
|
|
184
|
-
|
|
185
|
-
const rows: string[] = [];
|
|
186
|
-
rows.push(headers.map((h) => this.formatCsvValue(h)).join(","));
|
|
187
|
-
|
|
188
|
-
// Get all requirements (they're not paginated in the original service)
|
|
189
|
-
const q = includeInactive
|
|
190
|
-
? query(this.requirementsRef, orderBy("name"))
|
|
191
|
-
: query(this.requirementsRef, where("isActive", "==", true), orderBy("name"));
|
|
192
|
-
|
|
193
|
-
const snapshot = await getDocs(q);
|
|
194
|
-
|
|
195
|
-
for (const d of snapshot.docs) {
|
|
196
|
-
const requirement = ({ id: d.id, ...d.data() } as unknown) as Requirement;
|
|
197
|
-
rows.push(this.requirementToCsvRow(requirement));
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
const csvBody = rows.join("\r\n");
|
|
201
|
-
return includeBom ? "\uFEFF" + csvBody : csvBody;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
private requirementToCsvRow(requirement: Requirement): string {
|
|
205
|
-
const values = [
|
|
206
|
-
requirement.id ?? "",
|
|
207
|
-
requirement.type ?? "",
|
|
208
|
-
requirement.name ?? "",
|
|
209
|
-
requirement.description ?? "",
|
|
210
|
-
requirement.timeframe?.duration?.toString() ?? "",
|
|
211
|
-
requirement.timeframe?.unit ?? "",
|
|
212
|
-
requirement.timeframe?.notifyAt?.join(";") ?? "",
|
|
213
|
-
requirement.importance ?? "",
|
|
214
|
-
String(requirement.isActive ?? ""),
|
|
215
|
-
];
|
|
216
|
-
return values.map((v) => this.formatCsvValue(v)).join(",");
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
private formatDateIso(value: any): string {
|
|
220
|
-
// Firestore timestamps may come back as Date or Timestamp; handle both
|
|
221
|
-
if (value instanceof Date) return value.toISOString();
|
|
222
|
-
if (value && typeof value.toDate === "function") {
|
|
223
|
-
const d = value.toDate();
|
|
224
|
-
return d instanceof Date ? d.toISOString() : String(value);
|
|
225
|
-
}
|
|
226
|
-
return String(value ?? "");
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
private formatCsvValue(value: any): string {
|
|
230
|
-
const str = value === null || value === undefined ? "" : String(value);
|
|
231
|
-
// Escape double quotes by doubling them and wrap in quotes
|
|
232
|
-
const escaped = str.replace(/"/g, '""');
|
|
233
|
-
return `"${escaped}"`;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
addDoc,
|
|
3
|
+
collection,
|
|
4
|
+
doc,
|
|
5
|
+
getDoc,
|
|
6
|
+
getDocs,
|
|
7
|
+
query,
|
|
8
|
+
updateDoc,
|
|
9
|
+
where,
|
|
10
|
+
orderBy,
|
|
11
|
+
} from "firebase/firestore";
|
|
12
|
+
import {
|
|
13
|
+
Requirement,
|
|
14
|
+
RequirementType,
|
|
15
|
+
REQUIREMENTS_COLLECTION,
|
|
16
|
+
} from "../types/requirement.types";
|
|
17
|
+
import { BaseService } from "../../services/base.service";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Servis za upravljanje globalnim zahtevima.
|
|
21
|
+
* Zahtevi se mogu kreirati globalno i zatim povezati sa različitim tehnologijama.
|
|
22
|
+
* Ovo omogućava ponovno korišćenje istih zahteva za različite tehnologije.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* const requirementService = new RequirementService();
|
|
26
|
+
*
|
|
27
|
+
* // Kreiranje globalnog zahteva
|
|
28
|
+
* const requirement = await requirementService.create({
|
|
29
|
+
* type: "pre",
|
|
30
|
+
* name: "Stay Hydrated",
|
|
31
|
+
* description: "Drink plenty of water",
|
|
32
|
+
* timeframe: {
|
|
33
|
+
* duration: 2,
|
|
34
|
+
* unit: "hours",
|
|
35
|
+
* notifyAt: [2, 1]
|
|
36
|
+
* },
|
|
37
|
+
* importance: "high"
|
|
38
|
+
* });
|
|
39
|
+
*/
|
|
40
|
+
export class RequirementService extends BaseService {
|
|
41
|
+
/**
|
|
42
|
+
* Referenca na Firestore kolekciju zahteva
|
|
43
|
+
*/
|
|
44
|
+
private get requirementsRef() {
|
|
45
|
+
return collection(this.db, REQUIREMENTS_COLLECTION);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Kreira novi globalni zahtev
|
|
50
|
+
* @param requirement - Podaci za novi zahtev
|
|
51
|
+
* @returns Kreirani zahtev sa generisanim ID-em
|
|
52
|
+
*/
|
|
53
|
+
async create(
|
|
54
|
+
requirement: Omit<Requirement, "id" | "createdAt" | "updatedAt">
|
|
55
|
+
) {
|
|
56
|
+
const now = new Date();
|
|
57
|
+
const newRequirement: Omit<Requirement, "id"> = {
|
|
58
|
+
...requirement,
|
|
59
|
+
createdAt: now,
|
|
60
|
+
updatedAt: now,
|
|
61
|
+
isActive: true,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const docRef = await addDoc(this.requirementsRef, newRequirement);
|
|
65
|
+
return { id: docRef.id, ...newRequirement };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Vraća sve aktivne zahteve
|
|
70
|
+
* @returns Lista aktivnih zahteva
|
|
71
|
+
*/
|
|
72
|
+
async getAll() {
|
|
73
|
+
const q = query(this.requirementsRef, where("isActive", "==", true));
|
|
74
|
+
const snapshot = await getDocs(q);
|
|
75
|
+
return snapshot.docs.map(
|
|
76
|
+
(doc) =>
|
|
77
|
+
({
|
|
78
|
+
id: doc.id,
|
|
79
|
+
...doc.data(),
|
|
80
|
+
} as Requirement)
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Vraća sve aktivne zahteve određenog tipa
|
|
86
|
+
* @param type - Tip zahteva (pre/post)
|
|
87
|
+
* @returns Lista zahteva određenog tipa
|
|
88
|
+
*/
|
|
89
|
+
async getAllByType(type: RequirementType) {
|
|
90
|
+
const q = query(
|
|
91
|
+
this.requirementsRef,
|
|
92
|
+
where("type", "==", type),
|
|
93
|
+
where("isActive", "==", true)
|
|
94
|
+
);
|
|
95
|
+
const snapshot = await getDocs(q);
|
|
96
|
+
return snapshot.docs.map(
|
|
97
|
+
(doc) =>
|
|
98
|
+
({
|
|
99
|
+
id: doc.id,
|
|
100
|
+
...doc.data(),
|
|
101
|
+
} as Requirement)
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Searches for requirements by name.
|
|
107
|
+
* @param name - The name to search for.
|
|
108
|
+
* @param type - The type of requirement (pre/post).
|
|
109
|
+
* @returns A list of requirements that match the search criteria.
|
|
110
|
+
*/
|
|
111
|
+
async search(name: string, type: RequirementType) {
|
|
112
|
+
const requirements = await this.getAllByType(type);
|
|
113
|
+
return requirements.filter((r) =>
|
|
114
|
+
r.name.toLowerCase().includes(name.toLowerCase())
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Ažurira postojeći zahtev
|
|
120
|
+
* @param id - ID zahteva koji se ažurira
|
|
121
|
+
* @param requirement - Novi podaci za zahtev
|
|
122
|
+
* @returns Ažurirani zahtev
|
|
123
|
+
*/
|
|
124
|
+
async update(
|
|
125
|
+
id: string,
|
|
126
|
+
requirement: Partial<Omit<Requirement, "id" | "createdAt">>
|
|
127
|
+
) {
|
|
128
|
+
const updateData = {
|
|
129
|
+
...requirement,
|
|
130
|
+
updatedAt: new Date(),
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const docRef = doc(this.requirementsRef, id);
|
|
134
|
+
await updateDoc(docRef, updateData);
|
|
135
|
+
return this.getById(id);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Soft delete zahteva (postavlja isActive na false)
|
|
140
|
+
* @param id - ID zahteva koji se briše
|
|
141
|
+
*/
|
|
142
|
+
async delete(id: string) {
|
|
143
|
+
await this.update(id, { isActive: false });
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Vraća zahtev po ID-u
|
|
148
|
+
* @param id - ID traženog zahteva
|
|
149
|
+
* @returns Zahtev ili null ako ne postoji
|
|
150
|
+
*/
|
|
151
|
+
async getById(id: string) {
|
|
152
|
+
const docRef = doc(this.requirementsRef, id);
|
|
153
|
+
const docSnap = await getDoc(docRef);
|
|
154
|
+
if (!docSnap.exists()) return null;
|
|
155
|
+
return {
|
|
156
|
+
id: docSnap.id,
|
|
157
|
+
...docSnap.data(),
|
|
158
|
+
} as Requirement;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Exports requirements to CSV string, suitable for Excel/Sheets.
|
|
163
|
+
* Includes headers and optional UTF-8 BOM.
|
|
164
|
+
* By default exports only active requirements (set includeInactive to true to export all).
|
|
165
|
+
*/
|
|
166
|
+
async exportToCsv(options?: {
|
|
167
|
+
includeInactive?: boolean;
|
|
168
|
+
includeBom?: boolean;
|
|
169
|
+
}): Promise<string> {
|
|
170
|
+
const includeInactive = options?.includeInactive ?? false;
|
|
171
|
+
const includeBom = options?.includeBom ?? true;
|
|
172
|
+
|
|
173
|
+
const headers = [
|
|
174
|
+
"id",
|
|
175
|
+
"type",
|
|
176
|
+
"name",
|
|
177
|
+
"description",
|
|
178
|
+
"timeframe_duration",
|
|
179
|
+
"timeframe_unit",
|
|
180
|
+
"timeframe_notifyAt",
|
|
181
|
+
"importance",
|
|
182
|
+
"isActive",
|
|
183
|
+
];
|
|
184
|
+
|
|
185
|
+
const rows: string[] = [];
|
|
186
|
+
rows.push(headers.map((h) => this.formatCsvValue(h)).join(","));
|
|
187
|
+
|
|
188
|
+
// Get all requirements (they're not paginated in the original service)
|
|
189
|
+
const q = includeInactive
|
|
190
|
+
? query(this.requirementsRef, orderBy("name"))
|
|
191
|
+
: query(this.requirementsRef, where("isActive", "==", true), orderBy("name"));
|
|
192
|
+
|
|
193
|
+
const snapshot = await getDocs(q);
|
|
194
|
+
|
|
195
|
+
for (const d of snapshot.docs) {
|
|
196
|
+
const requirement = ({ id: d.id, ...d.data() } as unknown) as Requirement;
|
|
197
|
+
rows.push(this.requirementToCsvRow(requirement));
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const csvBody = rows.join("\r\n");
|
|
201
|
+
return includeBom ? "\uFEFF" + csvBody : csvBody;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
private requirementToCsvRow(requirement: Requirement): string {
|
|
205
|
+
const values = [
|
|
206
|
+
requirement.id ?? "",
|
|
207
|
+
requirement.type ?? "",
|
|
208
|
+
requirement.name ?? "",
|
|
209
|
+
requirement.description ?? "",
|
|
210
|
+
requirement.timeframe?.duration?.toString() ?? "",
|
|
211
|
+
requirement.timeframe?.unit ?? "",
|
|
212
|
+
requirement.timeframe?.notifyAt?.join(";") ?? "",
|
|
213
|
+
requirement.importance ?? "",
|
|
214
|
+
String(requirement.isActive ?? ""),
|
|
215
|
+
];
|
|
216
|
+
return values.map((v) => this.formatCsvValue(v)).join(",");
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
private formatDateIso(value: any): string {
|
|
220
|
+
// Firestore timestamps may come back as Date or Timestamp; handle both
|
|
221
|
+
if (value instanceof Date) return value.toISOString();
|
|
222
|
+
if (value && typeof value.toDate === "function") {
|
|
223
|
+
const d = value.toDate();
|
|
224
|
+
return d instanceof Date ? d.toISOString() : String(value);
|
|
225
|
+
}
|
|
226
|
+
return String(value ?? "");
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
private formatCsvValue(value: any): string {
|
|
230
|
+
const str = value === null || value === undefined ? "" : String(value);
|
|
231
|
+
// Escape double quotes by doubling them and wrap in quotes
|
|
232
|
+
const escaped = str.replace(/"/g, '""');
|
|
233
|
+
return `"${escaped}"`;
|
|
234
|
+
}
|
|
235
|
+
}
|