@blackcode_sa/metaestetics-api 1.8.3 → 1.8.5

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/index.mjs CHANGED
@@ -802,6 +802,9 @@ var Gender = /* @__PURE__ */ ((Gender2) => {
802
802
  // src/types/procedure/index.ts
803
803
  var PROCEDURES_COLLECTION = "procedures";
804
804
 
805
+ // src/backoffice/types/technology.types.ts
806
+ var TECHNOLOGIES_COLLECTION = "technologies";
807
+
805
808
  // src/services/appointment/utils/appointment.utils.ts
806
809
  async function updateAppointmentUtil(db, appointmentId, data) {
807
810
  try {
@@ -978,7 +981,7 @@ async function searchAppointmentsUtil(db, params) {
978
981
  const q = query(collection(db, APPOINTMENTS_COLLECTION), ...constraints);
979
982
  const querySnapshot = await getDocs(q);
980
983
  const appointments = querySnapshot.docs.map(
981
- (doc32) => doc32.data()
984
+ (doc38) => doc38.data()
982
985
  );
983
986
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
984
987
  return { appointments, lastDoc };
@@ -1785,7 +1788,7 @@ var AppointmentService = class extends BaseService {
1785
1788
  );
1786
1789
  const querySnapshot = await getDocs2(q);
1787
1790
  const appointments = querySnapshot.docs.map(
1788
- (doc32) => doc32.data()
1791
+ (doc38) => doc38.data()
1789
1792
  );
1790
1793
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
1791
1794
  console.log(
@@ -1858,7 +1861,7 @@ var AppointmentService = class extends BaseService {
1858
1861
  );
1859
1862
  const querySnapshot = await getDocs2(q);
1860
1863
  const appointments = querySnapshot.docs.map(
1861
- (doc32) => doc32.data()
1864
+ (doc38) => doc38.data()
1862
1865
  );
1863
1866
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
1864
1867
  console.log(
@@ -2152,16 +2155,16 @@ var CertificationLevel = /* @__PURE__ */ ((CertificationLevel2) => {
2152
2155
  CertificationLevel2["PLASTIC_SURGEON"] = "plastic_surgeon";
2153
2156
  return CertificationLevel2;
2154
2157
  })(CertificationLevel || {});
2155
- var CertificationSpecialty = /* @__PURE__ */ ((CertificationSpecialty2) => {
2156
- CertificationSpecialty2["LASER"] = "laser";
2157
- CertificationSpecialty2["INJECTABLES"] = "injectables";
2158
- CertificationSpecialty2["CHEMICAL_PEELS"] = "chemical_peels";
2159
- CertificationSpecialty2["MICRODERMABRASION"] = "microdermabrasion";
2160
- CertificationSpecialty2["BODY_CONTOURING"] = "body_contouring";
2161
- CertificationSpecialty2["SKIN_CARE"] = "skin_care";
2162
- CertificationSpecialty2["WOUND_CARE"] = "wound_care";
2163
- CertificationSpecialty2["ANESTHESIA"] = "anesthesia";
2164
- return CertificationSpecialty2;
2158
+ var CertificationSpecialty = /* @__PURE__ */ ((CertificationSpecialty3) => {
2159
+ CertificationSpecialty3["LASER"] = "laser";
2160
+ CertificationSpecialty3["INJECTABLES"] = "injectables";
2161
+ CertificationSpecialty3["CHEMICAL_PEELS"] = "chemical_peels";
2162
+ CertificationSpecialty3["MICRODERMABRASION"] = "microdermabrasion";
2163
+ CertificationSpecialty3["BODY_CONTOURING"] = "body_contouring";
2164
+ CertificationSpecialty3["SKIN_CARE"] = "skin_care";
2165
+ CertificationSpecialty3["WOUND_CARE"] = "wound_care";
2166
+ CertificationSpecialty3["ANESTHESIA"] = "anesthesia";
2167
+ return CertificationSpecialty3;
2165
2168
  })(CertificationSpecialty || {});
2166
2169
 
2167
2170
  // src/services/auth/utils/practitioner.utils.ts
@@ -3167,7 +3170,7 @@ var MediaService = class extends BaseService {
3167
3170
  try {
3168
3171
  const querySnapshot = await getDocs3(finalQuery);
3169
3172
  const mediaList = querySnapshot.docs.map(
3170
- (doc32) => doc32.data()
3173
+ (doc38) => doc38.data()
3171
3174
  );
3172
3175
  console.log(`[MediaService] Found ${mediaList.length} media items.`);
3173
3176
  return mediaList;
@@ -3230,8 +3233,8 @@ var getPatientsByClinicUtil = async (db, clinicId, options) => {
3230
3233
  }
3231
3234
  const patientsSnapshot = await getDocs4(q);
3232
3235
  const patients = [];
3233
- patientsSnapshot.forEach((doc32) => {
3234
- patients.push(doc32.data());
3236
+ patientsSnapshot.forEach((doc38) => {
3237
+ patients.push(doc38.data());
3235
3238
  });
3236
3239
  console.log(
3237
3240
  `[getPatientsByClinicUtil] Found ${patients.length} patients for clinic ID: ${clinicId}`
@@ -3605,8 +3608,8 @@ var getPatientsByPractitionerUtil = async (db, practitionerId, options) => {
3605
3608
  }
3606
3609
  const patientsSnapshot = await getDocs5(q);
3607
3610
  const patients = [];
3608
- patientsSnapshot.forEach((doc32) => {
3609
- patients.push(doc32.data());
3611
+ patientsSnapshot.forEach((doc38) => {
3612
+ patients.push(doc38.data());
3610
3613
  });
3611
3614
  console.log(
3612
3615
  `[getPatientsByPractitionerUtil] Found ${patients.length} patients for practitioner ID: ${practitionerId}`
@@ -4186,7 +4189,7 @@ async function getClinicAdminsByGroup(db, clinicGroupId) {
4186
4189
  where6("clinicGroupId", "==", clinicGroupId)
4187
4190
  );
4188
4191
  const querySnapshot = await getDocs6(q);
4189
- return querySnapshot.docs.map((doc32) => doc32.data());
4192
+ return querySnapshot.docs.map((doc38) => doc38.data());
4190
4193
  }
4191
4194
  async function updateClinicAdmin(db, adminId, data) {
4192
4195
  const admin2 = await getClinicAdmin(db, adminId);
@@ -4867,9 +4870,9 @@ var updateAllergyUtil = async (db, patientId, data, requesterId, requesterRoles)
4867
4870
  };
4868
4871
  var removeAllergyUtil = async (db, patientId, allergyIndex, requesterId, requesterRoles) => {
4869
4872
  await checkMedicalAccessUtil(db, patientId, requesterId, requesterRoles);
4870
- const doc32 = await getDoc10(getMedicalInfoDocRef(db, patientId));
4871
- if (!doc32.exists()) throw new Error("Medical info not found");
4872
- const medicalInfo = doc32.data();
4873
+ const doc38 = await getDoc10(getMedicalInfoDocRef(db, patientId));
4874
+ if (!doc38.exists()) throw new Error("Medical info not found");
4875
+ const medicalInfo = doc38.data();
4873
4876
  if (allergyIndex >= medicalInfo.allergies.length) {
4874
4877
  throw new Error("Invalid allergy index");
4875
4878
  }
@@ -4896,9 +4899,9 @@ var updateBlockingConditionUtil = async (db, patientId, data, requesterId, reque
4896
4899
  await checkMedicalAccessUtil(db, patientId, requesterId, requesterRoles);
4897
4900
  const validatedData = updateBlockingConditionSchema.parse(data);
4898
4901
  const { conditionIndex, ...updateData } = validatedData;
4899
- const doc32 = await getDoc10(getMedicalInfoDocRef(db, patientId));
4900
- if (!doc32.exists()) throw new Error("Medical info not found");
4901
- const medicalInfo = doc32.data();
4902
+ const doc38 = await getDoc10(getMedicalInfoDocRef(db, patientId));
4903
+ if (!doc38.exists()) throw new Error("Medical info not found");
4904
+ const medicalInfo = doc38.data();
4902
4905
  if (conditionIndex >= medicalInfo.blockingConditions.length) {
4903
4906
  throw new Error("Invalid blocking condition index");
4904
4907
  }
@@ -4915,9 +4918,9 @@ var updateBlockingConditionUtil = async (db, patientId, data, requesterId, reque
4915
4918
  };
4916
4919
  var removeBlockingConditionUtil = async (db, patientId, conditionIndex, requesterId, requesterRoles) => {
4917
4920
  await checkMedicalAccessUtil(db, patientId, requesterId, requesterRoles);
4918
- const doc32 = await getDoc10(getMedicalInfoDocRef(db, patientId));
4919
- if (!doc32.exists()) throw new Error("Medical info not found");
4920
- const medicalInfo = doc32.data();
4921
+ const doc38 = await getDoc10(getMedicalInfoDocRef(db, patientId));
4922
+ if (!doc38.exists()) throw new Error("Medical info not found");
4923
+ const medicalInfo = doc38.data();
4921
4924
  if (conditionIndex >= medicalInfo.blockingConditions.length) {
4922
4925
  throw new Error("Invalid blocking condition index");
4923
4926
  }
@@ -4944,9 +4947,9 @@ var updateContraindicationUtil = async (db, patientId, data, requesterId, reques
4944
4947
  await checkMedicalAccessUtil(db, patientId, requesterId, requesterRoles);
4945
4948
  const validatedData = updateContraindicationSchema.parse(data);
4946
4949
  const { contraindicationIndex, ...updateData } = validatedData;
4947
- const doc32 = await getDoc10(getMedicalInfoDocRef(db, patientId));
4948
- if (!doc32.exists()) throw new Error("Medical info not found");
4949
- const medicalInfo = doc32.data();
4950
+ const doc38 = await getDoc10(getMedicalInfoDocRef(db, patientId));
4951
+ if (!doc38.exists()) throw new Error("Medical info not found");
4952
+ const medicalInfo = doc38.data();
4950
4953
  if (contraindicationIndex >= medicalInfo.contraindications.length) {
4951
4954
  throw new Error("Invalid contraindication index");
4952
4955
  }
@@ -4963,9 +4966,9 @@ var updateContraindicationUtil = async (db, patientId, data, requesterId, reques
4963
4966
  };
4964
4967
  var removeContraindicationUtil = async (db, patientId, contraindicationIndex, requesterId, requesterRoles) => {
4965
4968
  await checkMedicalAccessUtil(db, patientId, requesterId, requesterRoles);
4966
- const doc32 = await getDoc10(getMedicalInfoDocRef(db, patientId));
4967
- if (!doc32.exists()) throw new Error("Medical info not found");
4968
- const medicalInfo = doc32.data();
4969
+ const doc38 = await getDoc10(getMedicalInfoDocRef(db, patientId));
4970
+ if (!doc38.exists()) throw new Error("Medical info not found");
4971
+ const medicalInfo = doc38.data();
4969
4972
  if (contraindicationIndex >= medicalInfo.contraindications.length) {
4970
4973
  throw new Error("Invalid contraindication index");
4971
4974
  }
@@ -4992,9 +4995,9 @@ var updateMedicationUtil = async (db, patientId, data, requesterId, requesterRol
4992
4995
  await checkMedicalAccessUtil(db, patientId, requesterId, requesterRoles);
4993
4996
  const validatedData = updateMedicationSchema.parse(data);
4994
4997
  const { medicationIndex, ...updateData } = validatedData;
4995
- const doc32 = await getDoc10(getMedicalInfoDocRef(db, patientId));
4996
- if (!doc32.exists()) throw new Error("Medical info not found");
4997
- const medicalInfo = doc32.data();
4998
+ const doc38 = await getDoc10(getMedicalInfoDocRef(db, patientId));
4999
+ if (!doc38.exists()) throw new Error("Medical info not found");
5000
+ const medicalInfo = doc38.data();
4998
5001
  if (medicationIndex >= medicalInfo.currentMedications.length) {
4999
5002
  throw new Error("Invalid medication index");
5000
5003
  }
@@ -5011,9 +5014,9 @@ var updateMedicationUtil = async (db, patientId, data, requesterId, requesterRol
5011
5014
  };
5012
5015
  var removeMedicationUtil = async (db, patientId, medicationIndex, requesterId, requesterRoles) => {
5013
5016
  await checkMedicalAccessUtil(db, patientId, requesterId, requesterRoles);
5014
- const doc32 = await getDoc10(getMedicalInfoDocRef(db, patientId));
5015
- if (!doc32.exists()) throw new Error("Medical info not found");
5016
- const medicalInfo = doc32.data();
5017
+ const doc38 = await getDoc10(getMedicalInfoDocRef(db, patientId));
5018
+ if (!doc38.exists()) throw new Error("Medical info not found");
5019
+ const medicalInfo = doc38.data();
5017
5020
  if (medicationIndex >= medicalInfo.currentMedications.length) {
5018
5021
  throw new Error("Invalid medication index");
5019
5022
  }
@@ -5316,7 +5319,7 @@ var searchPatientsUtil = async (db, params, requester) => {
5316
5319
  const finalQuery = query8(patientsCollectionRef, ...constraints);
5317
5320
  const querySnapshot = await getDocs8(finalQuery);
5318
5321
  const patients = querySnapshot.docs.map(
5319
- (doc32) => doc32.data()
5322
+ (doc38) => doc38.data()
5320
5323
  );
5321
5324
  console.log(
5322
5325
  `[searchPatientsUtil] Found ${patients.length} patients matching criteria.`
@@ -5348,8 +5351,8 @@ var getAllPatientsUtil = async (db, options) => {
5348
5351
  }
5349
5352
  const patientsSnapshot = await getDocs8(q);
5350
5353
  const patients = [];
5351
- patientsSnapshot.forEach((doc32) => {
5352
- patients.push(doc32.data());
5354
+ patientsSnapshot.forEach((doc38) => {
5355
+ patients.push(doc38.data());
5353
5356
  });
5354
5357
  console.log(`[getAllPatientsUtil] Found ${patients.length} patients`);
5355
5358
  return patients;
@@ -5482,7 +5485,7 @@ var getActiveInviteTokensByClinicUtil = async (db, clinicId) => {
5482
5485
  if (querySnapshot.empty) {
5483
5486
  return [];
5484
5487
  }
5485
- return querySnapshot.docs.map((doc32) => doc32.data());
5488
+ return querySnapshot.docs.map((doc38) => doc38.data());
5486
5489
  };
5487
5490
  var getActiveInviteTokensByPatientUtil = async (db, patientId) => {
5488
5491
  const tokensRef = collection9(
@@ -5500,7 +5503,7 @@ var getActiveInviteTokensByPatientUtil = async (db, patientId) => {
5500
5503
  if (querySnapshot.empty) {
5501
5504
  return [];
5502
5505
  }
5503
- return querySnapshot.docs.map((doc32) => doc32.data());
5506
+ return querySnapshot.docs.map((doc38) => doc38.data());
5504
5507
  };
5505
5508
 
5506
5509
  // src/services/patient/patient.service.ts
@@ -6623,7 +6626,7 @@ var PractitionerService = class extends BaseService {
6623
6626
  where10("expiresAt", ">", Timestamp14.now())
6624
6627
  );
6625
6628
  const querySnapshot = await getDocs10(q);
6626
- return querySnapshot.docs.map((doc32) => doc32.data());
6629
+ return querySnapshot.docs.map((doc38) => doc38.data());
6627
6630
  }
6628
6631
  /**
6629
6632
  * Gets a token by its string value and validates it
@@ -6733,7 +6736,7 @@ var PractitionerService = class extends BaseService {
6733
6736
  where10("status", "==", "active" /* ACTIVE */)
6734
6737
  );
6735
6738
  const querySnapshot = await getDocs10(q);
6736
- return querySnapshot.docs.map((doc32) => doc32.data());
6739
+ return querySnapshot.docs.map((doc38) => doc38.data());
6737
6740
  }
6738
6741
  /**
6739
6742
  * Dohvata sve zdravstvene radnike za određenu kliniku
@@ -6745,7 +6748,7 @@ var PractitionerService = class extends BaseService {
6745
6748
  where10("isActive", "==", true)
6746
6749
  );
6747
6750
  const querySnapshot = await getDocs10(q);
6748
- return querySnapshot.docs.map((doc32) => doc32.data());
6751
+ return querySnapshot.docs.map((doc38) => doc38.data());
6749
6752
  }
6750
6753
  /**
6751
6754
  * Dohvata sve draft zdravstvene radnike za određenu kliniku sa statusom DRAFT
@@ -6757,7 +6760,7 @@ var PractitionerService = class extends BaseService {
6757
6760
  where10("status", "==", "draft" /* DRAFT */)
6758
6761
  );
6759
6762
  const querySnapshot = await getDocs10(q);
6760
- return querySnapshot.docs.map((doc32) => doc32.data());
6763
+ return querySnapshot.docs.map((doc38) => doc38.data());
6761
6764
  }
6762
6765
  /**
6763
6766
  * Updates a practitioner
@@ -6971,7 +6974,7 @@ var PractitionerService = class extends BaseService {
6971
6974
  );
6972
6975
  const querySnapshot = await getDocs10(q);
6973
6976
  const practitioners = querySnapshot.docs.map(
6974
- (doc32) => doc32.data()
6977
+ (doc38) => doc38.data()
6975
6978
  );
6976
6979
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
6977
6980
  return {
@@ -7042,8 +7045,8 @@ var PractitionerService = class extends BaseService {
7042
7045
  console.log(
7043
7046
  `[PRACTITIONER_SERVICE] Found ${querySnapshot.docs.length} practitioners with base query`
7044
7047
  );
7045
- let practitioners = querySnapshot.docs.map((doc32) => {
7046
- return { ...doc32.data(), id: doc32.id };
7048
+ let practitioners = querySnapshot.docs.map((doc38) => {
7049
+ return { ...doc38.data(), id: doc38.id };
7047
7050
  });
7048
7051
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
7049
7052
  if (filters.nameSearch && filters.nameSearch.trim() !== "") {
@@ -7527,7 +7530,7 @@ var UserService = class extends BaseService {
7527
7530
  ];
7528
7531
  const q = query11(collection11(this.db, USERS_COLLECTION), ...constraints);
7529
7532
  const querySnapshot = await getDocs11(q);
7530
- const users = querySnapshot.docs.map((doc32) => doc32.data());
7533
+ const users = querySnapshot.docs.map((doc38) => doc38.data());
7531
7534
  return users.map((userData) => userSchema.parse(userData));
7532
7535
  }
7533
7536
  /**
@@ -7907,7 +7910,7 @@ async function getAllActiveGroups(db) {
7907
7910
  where12("isActive", "==", true)
7908
7911
  );
7909
7912
  const querySnapshot = await getDocs12(q);
7910
- return querySnapshot.docs.map((doc32) => doc32.data());
7913
+ return querySnapshot.docs.map((doc38) => doc38.data());
7911
7914
  }
7912
7915
  async function updateClinicGroup(db, groupId, data, app) {
7913
7916
  console.log("[CLINIC_GROUP] Updating clinic group", { groupId });
@@ -8372,7 +8375,7 @@ async function getClinicsByGroup(db, groupId) {
8372
8375
  where13("isActive", "==", true)
8373
8376
  );
8374
8377
  const querySnapshot = await getDocs13(q);
8375
- return querySnapshot.docs.map((doc32) => doc32.data());
8378
+ return querySnapshot.docs.map((doc38) => doc38.data());
8376
8379
  }
8377
8380
  async function updateClinic(db, clinicId, data, adminId, clinicAdminService, app) {
8378
8381
  console.log("[CLINIC] Starting clinic update", { clinicId, adminId });
@@ -8566,7 +8569,7 @@ async function getClinicsByAdmin(db, adminId, options = {}, clinicAdminService,
8566
8569
  }
8567
8570
  const q = query13(collection13(db, CLINICS_COLLECTION), ...constraints);
8568
8571
  const querySnapshot = await getDocs13(q);
8569
- return querySnapshot.docs.map((doc32) => doc32.data());
8572
+ return querySnapshot.docs.map((doc38) => doc38.data());
8570
8573
  }
8571
8574
  async function getActiveClinicsByAdmin(db, adminId, clinicAdminService, clinicGroupService) {
8572
8575
  return getClinicsByAdmin(
@@ -8611,11 +8614,11 @@ async function getAllClinics(db, pagination, lastDoc) {
8611
8614
  }
8612
8615
  const clinicsSnapshot = await getDocs13(clinicsQuery);
8613
8616
  const lastVisible = clinicsSnapshot.docs[clinicsSnapshot.docs.length - 1];
8614
- const clinics = clinicsSnapshot.docs.map((doc32) => {
8615
- const data = doc32.data();
8617
+ const clinics = clinicsSnapshot.docs.map((doc38) => {
8618
+ const data = doc38.data();
8616
8619
  return {
8617
8620
  ...data,
8618
- id: doc32.id
8621
+ id: doc38.id
8619
8622
  };
8620
8623
  });
8621
8624
  return {
@@ -8642,8 +8645,8 @@ async function getAllClinicsInRange(db, center, rangeInKm, pagination, lastDoc)
8642
8645
  ];
8643
8646
  const q = query13(collection13(db, CLINICS_COLLECTION), ...constraints);
8644
8647
  const querySnapshot = await getDocs13(q);
8645
- for (const doc32 of querySnapshot.docs) {
8646
- const clinic = doc32.data();
8648
+ for (const doc38 of querySnapshot.docs) {
8649
+ const clinic = doc38.data();
8647
8650
  const distance = distanceBetween2(
8648
8651
  [center.latitude, center.longitude],
8649
8652
  [clinic.location.latitude, clinic.location.longitude]
@@ -8765,8 +8768,8 @@ async function findClinicsInRadius(db, center, radiusInKm, filters) {
8765
8768
  }
8766
8769
  const q = query14(collection14(db, CLINICS_COLLECTION), ...constraints);
8767
8770
  const querySnapshot = await getDocs14(q);
8768
- for (const doc32 of querySnapshot.docs) {
8769
- const clinic = doc32.data();
8771
+ for (const doc38 of querySnapshot.docs) {
8772
+ const clinic = doc38.data();
8770
8773
  const distance = distanceBetween3(
8771
8774
  [center.latitude, center.longitude],
8772
8775
  [clinic.location.latitude, clinic.location.longitude]
@@ -8862,8 +8865,8 @@ async function getClinicsByFilters(db, filters) {
8862
8865
  console.log(
8863
8866
  `[FILTER_UTILS] Found ${querySnapshot.docs.length} clinics in geo bound`
8864
8867
  );
8865
- for (const doc32 of querySnapshot.docs) {
8866
- const clinic = { ...doc32.data(), id: doc32.id };
8868
+ for (const doc38 of querySnapshot.docs) {
8869
+ const clinic = { ...doc38.data(), id: doc38.id };
8867
8870
  const distance = distanceBetween4(
8868
8871
  [center.latitude, center.longitude],
8869
8872
  [clinic.location.latitude, clinic.location.longitude]
@@ -8919,8 +8922,8 @@ async function getClinicsByFilters(db, filters) {
8919
8922
  console.log(
8920
8923
  `[FILTER_UTILS] Found ${querySnapshot.docs.length} clinics with regular query`
8921
8924
  );
8922
- const clinics = querySnapshot.docs.map((doc32) => {
8923
- return { ...doc32.data(), id: doc32.id };
8925
+ const clinics = querySnapshot.docs.map((doc38) => {
8926
+ return { ...doc38.data(), id: doc38.id };
8924
8927
  });
8925
8928
  let filteredClinics = clinics;
8926
8929
  if (filters.center) {
@@ -10600,7 +10603,7 @@ async function searchCalendarEventsUtil(db, params) {
10600
10603
  const finalQuery = query21(collectionRef, ...constraints);
10601
10604
  const querySnapshot = await getDocs21(finalQuery);
10602
10605
  const events = querySnapshot.docs.map(
10603
- (doc32) => ({ id: doc32.id, ...doc32.data() })
10606
+ (doc38) => ({ id: doc38.id, ...doc38.data() })
10604
10607
  );
10605
10608
  return events;
10606
10609
  } catch (error) {
@@ -10693,7 +10696,7 @@ async function getPractitionerSyncedCalendarsUtil(db, practitionerId) {
10693
10696
  );
10694
10697
  const q = query22(calendarsRef, orderBy11("createdAt", "desc"));
10695
10698
  const querySnapshot = await getDocs22(q);
10696
- return querySnapshot.docs.map((doc32) => doc32.data());
10699
+ return querySnapshot.docs.map((doc38) => doc38.data());
10697
10700
  }
10698
10701
  async function getPatientSyncedCalendarUtil(db, patientId, calendarId) {
10699
10702
  const calendarRef = getPatientSyncedCalendarDocRef(db, patientId, calendarId);
@@ -10710,7 +10713,7 @@ async function getPatientSyncedCalendarsUtil(db, patientId) {
10710
10713
  );
10711
10714
  const q = query22(calendarsRef, orderBy11("createdAt", "desc"));
10712
10715
  const querySnapshot = await getDocs22(q);
10713
- return querySnapshot.docs.map((doc32) => doc32.data());
10716
+ return querySnapshot.docs.map((doc38) => doc38.data());
10714
10717
  }
10715
10718
  async function getClinicSyncedCalendarUtil(db, clinicId, calendarId) {
10716
10719
  const calendarRef = getClinicSyncedCalendarDocRef(db, clinicId, calendarId);
@@ -10727,7 +10730,7 @@ async function getClinicSyncedCalendarsUtil(db, clinicId) {
10727
10730
  );
10728
10731
  const q = query22(calendarsRef, orderBy11("createdAt", "desc"));
10729
10732
  const querySnapshot = await getDocs22(q);
10730
- return querySnapshot.docs.map((doc32) => doc32.data());
10733
+ return querySnapshot.docs.map((doc38) => doc38.data());
10731
10734
  }
10732
10735
  async function updatePractitionerSyncedCalendarUtil(db, practitionerId, calendarId, updateData) {
10733
10736
  const calendarRef = getPractitionerSyncedCalendarDocRef(
@@ -12082,9 +12085,9 @@ var CalendarServiceV2 = class extends BaseService {
12082
12085
  where23("eventTime.start", "<=", Timestamp26.fromDate(endDate))
12083
12086
  );
12084
12087
  const eventsSnapshot = await getDocs23(q);
12085
- const events = eventsSnapshot.docs.map((doc32) => ({
12086
- id: doc32.id,
12087
- ...doc32.data()
12088
+ const events = eventsSnapshot.docs.map((doc38) => ({
12089
+ id: doc38.id,
12090
+ ...doc38.data()
12088
12091
  }));
12089
12092
  const calendars = await this.syncedCalendarsService.getPractitionerSyncedCalendars(
12090
12093
  doctorId
@@ -12718,7 +12721,7 @@ var CalendarServiceV2 = class extends BaseService {
12718
12721
  ])
12719
12722
  );
12720
12723
  const querySnapshot = await getDocs23(q);
12721
- return querySnapshot.docs.map((doc32) => doc32.data());
12724
+ return querySnapshot.docs.map((doc38) => doc38.data());
12722
12725
  }
12723
12726
  /**
12724
12727
  * Calculates available time slots based on working hours, schedule and existing appointments
@@ -13263,7 +13266,7 @@ var PractitionerInviteService = class extends BaseService {
13263
13266
  ...constraints
13264
13267
  );
13265
13268
  const querySnapshot = await getDocs24(q);
13266
- return querySnapshot.docs.map((doc32) => doc32.data());
13269
+ return querySnapshot.docs.map((doc38) => doc38.data());
13267
13270
  } catch (error) {
13268
13271
  console.error(
13269
13272
  "[PractitionerInviteService] Error getting doctor invites:",
@@ -13292,7 +13295,7 @@ var PractitionerInviteService = class extends BaseService {
13292
13295
  ...constraints
13293
13296
  );
13294
13297
  const querySnapshot = await getDocs24(q);
13295
- return querySnapshot.docs.map((doc32) => doc32.data());
13298
+ return querySnapshot.docs.map((doc38) => doc38.data());
13296
13299
  } catch (error) {
13297
13300
  console.error(
13298
13301
  "[PractitionerInviteService] Error getting clinic invites:",
@@ -13448,7 +13451,7 @@ var PractitionerInviteService = class extends BaseService {
13448
13451
  );
13449
13452
  const querySnapshot = await getDocs24(q);
13450
13453
  let invites = querySnapshot.docs.map(
13451
- (doc32) => doc32.data()
13454
+ (doc38) => doc38.data()
13452
13455
  );
13453
13456
  if (filters.fromDate) {
13454
13457
  invites = invites.filter(
@@ -13718,8 +13721,8 @@ var DocumentationTemplateService = class extends BaseService {
13718
13721
  const q = query25(versionsCollectionRef, orderBy13("version", "desc"));
13719
13722
  const querySnapshot = await getDocs25(q);
13720
13723
  const versions = [];
13721
- querySnapshot.forEach((doc32) => {
13722
- versions.push(doc32.data());
13724
+ querySnapshot.forEach((doc38) => {
13725
+ versions.push(doc38.data());
13723
13726
  });
13724
13727
  return versions;
13725
13728
  }
@@ -13750,9 +13753,9 @@ var DocumentationTemplateService = class extends BaseService {
13750
13753
  const querySnapshot = await getDocs25(q);
13751
13754
  const templates = [];
13752
13755
  let lastVisible = null;
13753
- querySnapshot.forEach((doc32) => {
13754
- templates.push(doc32.data());
13755
- lastVisible = doc32;
13756
+ querySnapshot.forEach((doc38) => {
13757
+ templates.push(doc38.data());
13758
+ lastVisible = doc38;
13756
13759
  });
13757
13760
  return {
13758
13761
  templates,
@@ -13780,9 +13783,9 @@ var DocumentationTemplateService = class extends BaseService {
13780
13783
  const querySnapshot = await getDocs25(q);
13781
13784
  const templates = [];
13782
13785
  let lastVisible = null;
13783
- querySnapshot.forEach((doc32) => {
13784
- templates.push(doc32.data());
13785
- lastVisible = doc32;
13786
+ querySnapshot.forEach((doc38) => {
13787
+ templates.push(doc38.data());
13788
+ lastVisible = doc38;
13786
13789
  });
13787
13790
  return {
13788
13791
  templates,
@@ -13809,9 +13812,9 @@ var DocumentationTemplateService = class extends BaseService {
13809
13812
  const querySnapshot = await getDocs25(q);
13810
13813
  const templates = [];
13811
13814
  let lastVisible = null;
13812
- querySnapshot.forEach((doc32) => {
13813
- templates.push(doc32.data());
13814
- lastVisible = doc32;
13815
+ querySnapshot.forEach((doc38) => {
13816
+ templates.push(doc38.data());
13817
+ lastVisible = doc38;
13815
13818
  });
13816
13819
  return {
13817
13820
  templates,
@@ -13837,8 +13840,8 @@ var DocumentationTemplateService = class extends BaseService {
13837
13840
  }
13838
13841
  const querySnapshot = await getDocs25(q);
13839
13842
  const templates = [];
13840
- querySnapshot.forEach((doc32) => {
13841
- templates.push(doc32.data());
13843
+ querySnapshot.forEach((doc38) => {
13844
+ templates.push(doc38.data());
13842
13845
  });
13843
13846
  return templates;
13844
13847
  }
@@ -14044,9 +14047,9 @@ var FilledDocumentService = class extends BaseService {
14044
14047
  const querySnapshot = await getDocs26(q);
14045
14048
  const documents = [];
14046
14049
  let lastVisible = null;
14047
- querySnapshot.forEach((doc32) => {
14048
- documents.push(doc32.data());
14049
- lastVisible = doc32;
14050
+ querySnapshot.forEach((doc38) => {
14051
+ documents.push(doc38.data());
14052
+ lastVisible = doc38;
14050
14053
  });
14051
14054
  return {
14052
14055
  documents,
@@ -14268,9 +14271,9 @@ var NotificationService = class extends BaseService {
14268
14271
  orderBy15("notificationTime", "desc")
14269
14272
  );
14270
14273
  const querySnapshot = await getDocs27(q);
14271
- return querySnapshot.docs.map((doc32) => ({
14272
- id: doc32.id,
14273
- ...doc32.data()
14274
+ return querySnapshot.docs.map((doc38) => ({
14275
+ id: doc38.id,
14276
+ ...doc38.data()
14274
14277
  }));
14275
14278
  }
14276
14279
  /**
@@ -14284,9 +14287,9 @@ var NotificationService = class extends BaseService {
14284
14287
  orderBy15("notificationTime", "desc")
14285
14288
  );
14286
14289
  const querySnapshot = await getDocs27(q);
14287
- return querySnapshot.docs.map((doc32) => ({
14288
- id: doc32.id,
14289
- ...doc32.data()
14290
+ return querySnapshot.docs.map((doc38) => ({
14291
+ id: doc38.id,
14292
+ ...doc38.data()
14290
14293
  }));
14291
14294
  }
14292
14295
  /**
@@ -14358,9 +14361,9 @@ var NotificationService = class extends BaseService {
14358
14361
  orderBy15("notificationTime", "desc")
14359
14362
  );
14360
14363
  const querySnapshot = await getDocs27(q);
14361
- return querySnapshot.docs.map((doc32) => ({
14362
- id: doc32.id,
14363
- ...doc32.data()
14364
+ return querySnapshot.docs.map((doc38) => ({
14365
+ id: doc38.id,
14366
+ ...doc38.data()
14364
14367
  }));
14365
14368
  }
14366
14369
  /**
@@ -14373,9 +14376,9 @@ var NotificationService = class extends BaseService {
14373
14376
  orderBy15("notificationTime", "desc")
14374
14377
  );
14375
14378
  const querySnapshot = await getDocs27(q);
14376
- return querySnapshot.docs.map((doc32) => ({
14377
- id: doc32.id,
14378
- ...doc32.data()
14379
+ return querySnapshot.docs.map((doc38) => ({
14380
+ id: doc38.id,
14381
+ ...doc38.data()
14379
14382
  }));
14380
14383
  }
14381
14384
  };
@@ -14880,8 +14883,8 @@ var ProcedureService = class extends BaseService {
14880
14883
  where29(documentId2(), "in", chunk)
14881
14884
  );
14882
14885
  const practitionersSnapshot = await getDocs29(practitionersQuery);
14883
- practitionersSnapshot.docs.forEach((doc32) => {
14884
- practitionersMap.set(doc32.id, doc32.data());
14886
+ practitionersSnapshot.docs.forEach((doc38) => {
14887
+ practitionersMap.set(doc38.id, doc38.data());
14885
14888
  });
14886
14889
  }
14887
14890
  if (practitionersMap.size !== practitionerIds.length) {
@@ -14963,8 +14966,8 @@ var ProcedureService = class extends BaseService {
14963
14966
  where29(documentId2(), "in", chunk)
14964
14967
  );
14965
14968
  const snapshot = await getDocs29(q);
14966
- snapshot.forEach((doc32) => {
14967
- fetchedProcedures.push(doc32.data());
14969
+ snapshot.forEach((doc38) => {
14970
+ fetchedProcedures.push(doc38.data());
14968
14971
  });
14969
14972
  }
14970
14973
  return fetchedProcedures;
@@ -14994,7 +14997,7 @@ var ProcedureService = class extends BaseService {
14994
14997
  where29("isActive", "==", true)
14995
14998
  );
14996
14999
  const snapshot = await getDocs29(q);
14997
- return snapshot.docs.map((doc32) => doc32.data());
15000
+ return snapshot.docs.map((doc38) => doc38.data());
14998
15001
  }
14999
15002
  /**
15000
15003
  * Gets all procedures for a practitioner
@@ -15008,7 +15011,7 @@ var ProcedureService = class extends BaseService {
15008
15011
  where29("isActive", "==", true)
15009
15012
  );
15010
15013
  const snapshot = await getDocs29(q);
15011
- return snapshot.docs.map((doc32) => doc32.data());
15014
+ return snapshot.docs.map((doc38) => doc38.data());
15012
15015
  }
15013
15016
  /**
15014
15017
  * Gets all inactive procedures for a practitioner
@@ -15022,7 +15025,7 @@ var ProcedureService = class extends BaseService {
15022
15025
  where29("isActive", "==", false)
15023
15026
  );
15024
15027
  const snapshot = await getDocs29(q);
15025
- return snapshot.docs.map((doc32) => doc32.data());
15028
+ return snapshot.docs.map((doc38) => doc38.data());
15026
15029
  }
15027
15030
  /**
15028
15031
  * Updates a procedure
@@ -15234,11 +15237,11 @@ var ProcedureService = class extends BaseService {
15234
15237
  }
15235
15238
  const proceduresSnapshot = await getDocs29(proceduresQuery);
15236
15239
  const lastVisible = proceduresSnapshot.docs[proceduresSnapshot.docs.length - 1];
15237
- const procedures = proceduresSnapshot.docs.map((doc32) => {
15238
- const data = doc32.data();
15240
+ const procedures = proceduresSnapshot.docs.map((doc38) => {
15241
+ const data = doc38.data();
15239
15242
  return {
15240
15243
  ...data,
15241
- id: doc32.id
15244
+ id: doc38.id
15242
15245
  // Ensure ID is present
15243
15246
  };
15244
15247
  });
@@ -15320,8 +15323,8 @@ var ProcedureService = class extends BaseService {
15320
15323
  console.log(
15321
15324
  `[PROCEDURE_SERVICE] Found ${querySnapshot.docs.length} procedures in geo bound`
15322
15325
  );
15323
- for (const doc32 of querySnapshot.docs) {
15324
- const procedure = { ...doc32.data(), id: doc32.id };
15326
+ for (const doc38 of querySnapshot.docs) {
15327
+ const procedure = { ...doc38.data(), id: doc38.id };
15325
15328
  const distance = distanceBetween6(
15326
15329
  [center.latitude, center.longitude],
15327
15330
  [
@@ -15372,8 +15375,8 @@ var ProcedureService = class extends BaseService {
15372
15375
  console.log(
15373
15376
  `[PROCEDURE_SERVICE] Found ${querySnapshot.docs.length} procedures with regular query`
15374
15377
  );
15375
- const procedures = querySnapshot.docs.map((doc32) => {
15376
- return { ...doc32.data(), id: doc32.id };
15378
+ const procedures = querySnapshot.docs.map((doc38) => {
15379
+ return { ...doc38.data(), id: doc38.id };
15377
15380
  });
15378
15381
  if (filters.location) {
15379
15382
  const center = filters.location;
@@ -15716,7 +15719,7 @@ var ReviewService = class extends BaseService {
15716
15719
  where30("patientId", "==", patientId)
15717
15720
  );
15718
15721
  const snapshot = await getDocs30(q);
15719
- return snapshot.docs.map((doc32) => doc32.data());
15722
+ return snapshot.docs.map((doc38) => doc38.data());
15720
15723
  }
15721
15724
  /**
15722
15725
  * Gets all reviews for a specific clinic
@@ -15729,7 +15732,7 @@ var ReviewService = class extends BaseService {
15729
15732
  where30("clinicReview.clinicId", "==", clinicId)
15730
15733
  );
15731
15734
  const snapshot = await getDocs30(q);
15732
- return snapshot.docs.map((doc32) => doc32.data());
15735
+ return snapshot.docs.map((doc38) => doc38.data());
15733
15736
  }
15734
15737
  /**
15735
15738
  * Gets all reviews for a specific practitioner
@@ -15742,7 +15745,7 @@ var ReviewService = class extends BaseService {
15742
15745
  where30("practitionerReview.practitionerId", "==", practitionerId)
15743
15746
  );
15744
15747
  const snapshot = await getDocs30(q);
15745
- return snapshot.docs.map((doc32) => doc32.data());
15748
+ return snapshot.docs.map((doc38) => doc38.data());
15746
15749
  }
15747
15750
  /**
15748
15751
  * Gets all reviews for a specific procedure
@@ -15755,7 +15758,7 @@ var ReviewService = class extends BaseService {
15755
15758
  where30("procedureReview.procedureId", "==", procedureId)
15756
15759
  );
15757
15760
  const snapshot = await getDocs30(q);
15758
- return snapshot.docs.map((doc32) => doc32.data());
15761
+ return snapshot.docs.map((doc38) => doc38.data());
15759
15762
  }
15760
15763
  /**
15761
15764
  * Gets all reviews for a specific appointment
@@ -16068,11 +16071,12 @@ var TimeUnit = /* @__PURE__ */ ((TimeUnit2) => {
16068
16071
  TimeUnit2["DAYS"] = "days";
16069
16072
  return TimeUnit2;
16070
16073
  })(TimeUnit || {});
16071
- var RequirementType = /* @__PURE__ */ ((RequirementType2) => {
16072
- RequirementType2["PRE"] = "pre";
16073
- RequirementType2["POST"] = "post";
16074
- return RequirementType2;
16074
+ var RequirementType = /* @__PURE__ */ ((RequirementType3) => {
16075
+ RequirementType3["PRE"] = "pre";
16076
+ RequirementType3["POST"] = "post";
16077
+ return RequirementType3;
16075
16078
  })(RequirementType || {});
16079
+ var REQUIREMENTS_COLLECTION = "backoffice_requirements";
16076
16080
 
16077
16081
  // src/backoffice/validations/schemas.ts
16078
16082
  var blockingConditionSchemaBackoffice = z29.nativeEnum(BlockingCondition);
@@ -16421,6 +16425,1207 @@ var getFirebaseFunctions = async () => {
16421
16425
  const instance = await getFirebaseInstance();
16422
16426
  return instance.functions;
16423
16427
  };
16428
+
16429
+ // src/backoffice/services/brand.service.ts
16430
+ import {
16431
+ addDoc as addDoc3,
16432
+ collection as collection31,
16433
+ doc as doc32,
16434
+ getDoc as getDoc34,
16435
+ getDocs as getDocs31,
16436
+ query as query31,
16437
+ updateDoc as updateDoc30,
16438
+ where as where31
16439
+ } from "firebase/firestore";
16440
+
16441
+ // src/backoffice/types/brand.types.ts
16442
+ var BRANDS_COLLECTION = "brands";
16443
+
16444
+ // src/backoffice/services/brand.service.ts
16445
+ var BrandService = class extends BaseService {
16446
+ /**
16447
+ * Gets reference to brands collection
16448
+ */
16449
+ getBrandsRef() {
16450
+ return collection31(this.db, BRANDS_COLLECTION);
16451
+ }
16452
+ /**
16453
+ * Creates a new brand
16454
+ */
16455
+ async create(brand) {
16456
+ const now = /* @__PURE__ */ new Date();
16457
+ const newBrand = {
16458
+ ...brand,
16459
+ createdAt: now,
16460
+ updatedAt: now,
16461
+ isActive: true
16462
+ };
16463
+ const docRef = await addDoc3(this.getBrandsRef(), newBrand);
16464
+ return { id: docRef.id, ...newBrand };
16465
+ }
16466
+ /**
16467
+ * Gets all active brands
16468
+ */
16469
+ async getAll() {
16470
+ const q = query31(this.getBrandsRef(), where31("isActive", "==", true));
16471
+ const snapshot = await getDocs31(q);
16472
+ return snapshot.docs.map(
16473
+ (doc38) => ({
16474
+ id: doc38.id,
16475
+ ...doc38.data()
16476
+ })
16477
+ );
16478
+ }
16479
+ /**
16480
+ * Updates a brand
16481
+ */
16482
+ async update(brandId, brand) {
16483
+ const updateData = {
16484
+ ...brand,
16485
+ updatedAt: /* @__PURE__ */ new Date()
16486
+ };
16487
+ const docRef = doc32(this.getBrandsRef(), brandId);
16488
+ await updateDoc30(docRef, updateData);
16489
+ return this.getById(brandId);
16490
+ }
16491
+ /**
16492
+ * Soft deletes a brand
16493
+ */
16494
+ async delete(brandId) {
16495
+ await this.update(brandId, {
16496
+ isActive: false
16497
+ });
16498
+ }
16499
+ /**
16500
+ * Gets a brand by ID
16501
+ */
16502
+ async getById(brandId) {
16503
+ const docRef = doc32(this.getBrandsRef(), brandId);
16504
+ const docSnap = await getDoc34(docRef);
16505
+ if (!docSnap.exists()) return null;
16506
+ return {
16507
+ id: docSnap.id,
16508
+ ...docSnap.data()
16509
+ };
16510
+ }
16511
+ };
16512
+
16513
+ // src/backoffice/services/category.service.ts
16514
+ import {
16515
+ addDoc as addDoc4,
16516
+ collection as collection32,
16517
+ doc as doc33,
16518
+ getDoc as getDoc35,
16519
+ getDocs as getDocs32,
16520
+ query as query32,
16521
+ updateDoc as updateDoc31,
16522
+ where as where32
16523
+ } from "firebase/firestore";
16524
+
16525
+ // src/backoffice/types/category.types.ts
16526
+ var CATEGORIES_COLLECTION = "backoffice_categories";
16527
+
16528
+ // src/backoffice/services/category.service.ts
16529
+ var CategoryService = class extends BaseService {
16530
+ /**
16531
+ * Referenca na Firestore kolekciju kategorija
16532
+ */
16533
+ get categoriesRef() {
16534
+ return collection32(this.db, CATEGORIES_COLLECTION);
16535
+ }
16536
+ /**
16537
+ * Kreira novu kategoriju u sistemu
16538
+ * @param category - Podaci za novu kategoriju
16539
+ * @returns Kreirana kategorija sa generisanim ID-em
16540
+ */
16541
+ async create(category) {
16542
+ const now = /* @__PURE__ */ new Date();
16543
+ const newCategory = {
16544
+ ...category,
16545
+ createdAt: now,
16546
+ updatedAt: now,
16547
+ isActive: true
16548
+ };
16549
+ const docRef = await addDoc4(this.categoriesRef, newCategory);
16550
+ return { id: docRef.id, ...newCategory };
16551
+ }
16552
+ /**
16553
+ * Vraća sve aktivne kategorije
16554
+ * @returns Lista aktivnih kategorija
16555
+ */
16556
+ async getAll() {
16557
+ const q = query32(this.categoriesRef, where32("isActive", "==", true));
16558
+ const snapshot = await getDocs32(q);
16559
+ return snapshot.docs.map(
16560
+ (doc38) => ({
16561
+ id: doc38.id,
16562
+ ...doc38.data()
16563
+ })
16564
+ );
16565
+ }
16566
+ /**
16567
+ * Vraća sve aktivne kategorije za određenu familiju procedura
16568
+ * @param family - Familija procedura (aesthetics/surgery)
16569
+ * @returns Lista kategorija koje pripadaju traženoj familiji
16570
+ */
16571
+ async getAllByFamily(family) {
16572
+ const q = query32(
16573
+ this.categoriesRef,
16574
+ where32("family", "==", family),
16575
+ where32("isActive", "==", true)
16576
+ );
16577
+ const snapshot = await getDocs32(q);
16578
+ return snapshot.docs.map(
16579
+ (doc38) => ({
16580
+ id: doc38.id,
16581
+ ...doc38.data()
16582
+ })
16583
+ );
16584
+ }
16585
+ /**
16586
+ * Ažurira postojeću kategoriju
16587
+ * @param id - ID kategorije koja se ažurira
16588
+ * @param category - Novi podaci za kategoriju
16589
+ * @returns Ažurirana kategorija
16590
+ */
16591
+ async update(id, category) {
16592
+ const updateData = {
16593
+ ...category,
16594
+ updatedAt: /* @__PURE__ */ new Date()
16595
+ };
16596
+ const docRef = doc33(this.categoriesRef, id);
16597
+ await updateDoc31(docRef, updateData);
16598
+ return this.getById(id);
16599
+ }
16600
+ /**
16601
+ * Soft delete kategorije (postavlja isActive na false)
16602
+ * @param id - ID kategorije koja se briše
16603
+ */
16604
+ async delete(id) {
16605
+ await this.update(id, { isActive: false });
16606
+ }
16607
+ /**
16608
+ * Vraća kategoriju po ID-u
16609
+ * @param id - ID tražene kategorije
16610
+ * @returns Kategorija ili null ako ne postoji
16611
+ */
16612
+ async getById(id) {
16613
+ const docRef = doc33(this.categoriesRef, id);
16614
+ const docSnap = await getDoc35(docRef);
16615
+ if (!docSnap.exists()) return null;
16616
+ return {
16617
+ id: docSnap.id,
16618
+ ...docSnap.data()
16619
+ };
16620
+ }
16621
+ };
16622
+
16623
+ // src/backoffice/services/documentation-template.service.ts
16624
+ var DocumentationTemplateServiceBackoffice = class {
16625
+ /**
16626
+ * Constructor for DocumentationTemplateService
16627
+ * @param db - Firestore instance
16628
+ * @param auth - Firebase Auth instance
16629
+ * @param app - Firebase App instance
16630
+ */
16631
+ constructor(db, auth, app) {
16632
+ this.apiService = new DocumentationTemplateService(db, auth, app);
16633
+ }
16634
+ /**
16635
+ * Create a new document template
16636
+ * @param data - Template data
16637
+ * @param userId - ID of the user creating the template
16638
+ * @returns The created template
16639
+ */
16640
+ async createTemplate(data, userId) {
16641
+ return this.apiService.createTemplate(data, userId);
16642
+ }
16643
+ /**
16644
+ * Get a document template by ID
16645
+ * @param templateId - ID of the template to retrieve
16646
+ * @param version - Optional version number to retrieve (defaults to latest version)
16647
+ * @returns The template or null if not found
16648
+ */
16649
+ async getTemplateById(templateId, version) {
16650
+ return this.apiService.getTemplateById(templateId, version);
16651
+ }
16652
+ /**
16653
+ * Update an existing document template
16654
+ * @param templateId - ID of the template to update
16655
+ * @param data - Updated template data
16656
+ * @returns The updated template
16657
+ */
16658
+ async updateTemplate(templateId, data) {
16659
+ return this.apiService.updateTemplate(templateId, data);
16660
+ }
16661
+ /**
16662
+ * Delete a document template
16663
+ * @param templateId - ID of the template to delete
16664
+ */
16665
+ async deleteTemplate(templateId) {
16666
+ return this.apiService.deleteTemplate(templateId);
16667
+ }
16668
+ /**
16669
+ * Get all active templates
16670
+ * @param pageSize - Number of templates to retrieve
16671
+ * @param lastDoc - Last document from previous page for pagination
16672
+ * @returns Array of templates and the last document for pagination
16673
+ */
16674
+ async getActiveTemplates(pageSize = 20, lastDoc) {
16675
+ return this.apiService.getActiveTemplates(pageSize, lastDoc);
16676
+ }
16677
+ /**
16678
+ * Get templates by tags
16679
+ * @param tags - Tags to filter by
16680
+ * @param pageSize - Number of templates to retrieve
16681
+ * @param lastDoc - Last document from previous page for pagination
16682
+ * @returns Array of templates and the last document for pagination
16683
+ */
16684
+ async getTemplatesByTags(tags, pageSize = 20, lastDoc) {
16685
+ return this.apiService.getTemplatesByTags(tags, pageSize, lastDoc);
16686
+ }
16687
+ /**
16688
+ * Get templates created by a specific user
16689
+ * @param userId - ID of the user who created the templates
16690
+ * @param pageSize - Number of templates to retrieve
16691
+ * @param lastDoc - Last document from previous page for pagination
16692
+ * @returns Array of templates and the last document for pagination
16693
+ */
16694
+ async getTemplatesByCreator(userId, pageSize = 20, lastDoc) {
16695
+ return this.apiService.getTemplatesByCreator(userId, pageSize, lastDoc);
16696
+ }
16697
+ /**
16698
+ * Get a specific version of a template
16699
+ * @param templateId - ID of the template
16700
+ * @param versionNumber - Version number to retrieve
16701
+ * @returns The template version or null if not found
16702
+ */
16703
+ async getTemplateVersion(templateId, versionNumber) {
16704
+ return this.apiService.getTemplateVersion(templateId, versionNumber);
16705
+ }
16706
+ /**
16707
+ * Get all versions of a template
16708
+ * @param templateId - ID of the template
16709
+ * @returns Array of template versions
16710
+ */
16711
+ async getTemplateVersions(templateId) {
16712
+ return this.apiService.getTemplateOldVersions(templateId);
16713
+ }
16714
+ };
16715
+
16716
+ // src/backoffice/services/product.service.ts
16717
+ import {
16718
+ addDoc as addDoc5,
16719
+ collection as collection33,
16720
+ doc as doc34,
16721
+ getDoc as getDoc36,
16722
+ getDocs as getDocs33,
16723
+ query as query33,
16724
+ updateDoc as updateDoc32,
16725
+ where as where33
16726
+ } from "firebase/firestore";
16727
+
16728
+ // src/backoffice/types/product.types.ts
16729
+ var PRODUCTS_COLLECTION = "products";
16730
+
16731
+ // src/backoffice/services/product.service.ts
16732
+ var ProductService = class extends BaseService {
16733
+ /**
16734
+ * Gets reference to products collection under a technology
16735
+ * @param technologyId - ID of the technology
16736
+ * @returns Firestore collection reference
16737
+ */
16738
+ getProductsRef(technologyId) {
16739
+ return collection33(
16740
+ this.db,
16741
+ TECHNOLOGIES_COLLECTION,
16742
+ technologyId,
16743
+ PRODUCTS_COLLECTION
16744
+ );
16745
+ }
16746
+ /**
16747
+ * Creates a new product under technology
16748
+ */
16749
+ async create(technologyId, brandId, product) {
16750
+ const now = /* @__PURE__ */ new Date();
16751
+ const newProduct = {
16752
+ ...product,
16753
+ brandId,
16754
+ technologyId,
16755
+ createdAt: now,
16756
+ updatedAt: now,
16757
+ isActive: true
16758
+ };
16759
+ const productRef = await addDoc5(
16760
+ this.getProductsRef(technologyId),
16761
+ newProduct
16762
+ );
16763
+ return { id: productRef.id, ...newProduct };
16764
+ }
16765
+ /**
16766
+ * Gets all products for a technology
16767
+ */
16768
+ async getAllByTechnology(technologyId) {
16769
+ const q = query33(
16770
+ this.getProductsRef(technologyId),
16771
+ where33("isActive", "==", true)
16772
+ );
16773
+ const snapshot = await getDocs33(q);
16774
+ return snapshot.docs.map(
16775
+ (doc38) => ({
16776
+ id: doc38.id,
16777
+ ...doc38.data()
16778
+ })
16779
+ );
16780
+ }
16781
+ /**
16782
+ * Gets all products for a brand by filtering through all technologies
16783
+ */
16784
+ async getAllByBrand(brandId) {
16785
+ const allTechnologiesRef = collection33(this.db, TECHNOLOGIES_COLLECTION);
16786
+ const technologiesSnapshot = await getDocs33(allTechnologiesRef);
16787
+ const products = [];
16788
+ for (const techDoc of technologiesSnapshot.docs) {
16789
+ const q = query33(
16790
+ this.getProductsRef(techDoc.id),
16791
+ where33("brandId", "==", brandId),
16792
+ where33("isActive", "==", true)
16793
+ );
16794
+ const snapshot = await getDocs33(q);
16795
+ products.push(
16796
+ ...snapshot.docs.map(
16797
+ (doc38) => ({
16798
+ id: doc38.id,
16799
+ ...doc38.data()
16800
+ })
16801
+ )
16802
+ );
16803
+ }
16804
+ return products;
16805
+ }
16806
+ /**
16807
+ * Updates a product
16808
+ */
16809
+ async update(technologyId, productId, product) {
16810
+ const updateData = {
16811
+ ...product,
16812
+ updatedAt: /* @__PURE__ */ new Date()
16813
+ };
16814
+ const docRef = doc34(this.getProductsRef(technologyId), productId);
16815
+ await updateDoc32(docRef, updateData);
16816
+ return this.getById(technologyId, productId);
16817
+ }
16818
+ /**
16819
+ * Soft deletes a product
16820
+ */
16821
+ async delete(technologyId, productId) {
16822
+ await this.update(technologyId, productId, {
16823
+ isActive: false
16824
+ });
16825
+ }
16826
+ /**
16827
+ * Gets a product by ID
16828
+ */
16829
+ async getById(technologyId, productId) {
16830
+ const docRef = doc34(this.getProductsRef(technologyId), productId);
16831
+ const docSnap = await getDoc36(docRef);
16832
+ if (!docSnap.exists()) return null;
16833
+ return {
16834
+ id: docSnap.id,
16835
+ ...docSnap.data()
16836
+ };
16837
+ }
16838
+ };
16839
+
16840
+ // src/backoffice/services/requirement.service.ts
16841
+ import {
16842
+ addDoc as addDoc6,
16843
+ collection as collection34,
16844
+ doc as doc35,
16845
+ getDoc as getDoc37,
16846
+ getDocs as getDocs34,
16847
+ query as query34,
16848
+ updateDoc as updateDoc33,
16849
+ where as where34
16850
+ } from "firebase/firestore";
16851
+ var RequirementService = class extends BaseService {
16852
+ /**
16853
+ * Referenca na Firestore kolekciju zahteva
16854
+ */
16855
+ get requirementsRef() {
16856
+ return collection34(this.db, REQUIREMENTS_COLLECTION);
16857
+ }
16858
+ /**
16859
+ * Kreira novi globalni zahtev
16860
+ * @param requirement - Podaci za novi zahtev
16861
+ * @returns Kreirani zahtev sa generisanim ID-em
16862
+ */
16863
+ async create(requirement) {
16864
+ const now = /* @__PURE__ */ new Date();
16865
+ const newRequirement = {
16866
+ ...requirement,
16867
+ createdAt: now,
16868
+ updatedAt: now,
16869
+ isActive: true
16870
+ };
16871
+ const docRef = await addDoc6(this.requirementsRef, newRequirement);
16872
+ return { id: docRef.id, ...newRequirement };
16873
+ }
16874
+ /**
16875
+ * Vraća sve aktivne zahteve
16876
+ * @returns Lista aktivnih zahteva
16877
+ */
16878
+ async getAll() {
16879
+ const q = query34(this.requirementsRef, where34("isActive", "==", true));
16880
+ const snapshot = await getDocs34(q);
16881
+ return snapshot.docs.map(
16882
+ (doc38) => ({
16883
+ id: doc38.id,
16884
+ ...doc38.data()
16885
+ })
16886
+ );
16887
+ }
16888
+ /**
16889
+ * Vraća sve aktivne zahteve određenog tipa
16890
+ * @param type - Tip zahteva (pre/post)
16891
+ * @returns Lista zahteva određenog tipa
16892
+ */
16893
+ async getAllByType(type) {
16894
+ const q = query34(
16895
+ this.requirementsRef,
16896
+ where34("type", "==", type),
16897
+ where34("isActive", "==", true)
16898
+ );
16899
+ const snapshot = await getDocs34(q);
16900
+ return snapshot.docs.map(
16901
+ (doc38) => ({
16902
+ id: doc38.id,
16903
+ ...doc38.data()
16904
+ })
16905
+ );
16906
+ }
16907
+ /**
16908
+ * Ažurira postojeći zahtev
16909
+ * @param id - ID zahteva koji se ažurira
16910
+ * @param requirement - Novi podaci za zahtev
16911
+ * @returns Ažurirani zahtev
16912
+ */
16913
+ async update(id, requirement) {
16914
+ const updateData = {
16915
+ ...requirement,
16916
+ updatedAt: /* @__PURE__ */ new Date()
16917
+ };
16918
+ const docRef = doc35(this.requirementsRef, id);
16919
+ await updateDoc33(docRef, updateData);
16920
+ return this.getById(id);
16921
+ }
16922
+ /**
16923
+ * Soft delete zahteva (postavlja isActive na false)
16924
+ * @param id - ID zahteva koji se briše
16925
+ */
16926
+ async delete(id) {
16927
+ await this.update(id, { isActive: false });
16928
+ }
16929
+ /**
16930
+ * Vraća zahtev po ID-u
16931
+ * @param id - ID traženog zahteva
16932
+ * @returns Zahtev ili null ako ne postoji
16933
+ */
16934
+ async getById(id) {
16935
+ const docRef = doc35(this.requirementsRef, id);
16936
+ const docSnap = await getDoc37(docRef);
16937
+ if (!docSnap.exists()) return null;
16938
+ return {
16939
+ id: docSnap.id,
16940
+ ...docSnap.data()
16941
+ };
16942
+ }
16943
+ };
16944
+
16945
+ // src/backoffice/services/subcategory.service.ts
16946
+ import {
16947
+ addDoc as addDoc7,
16948
+ collection as collection35,
16949
+ doc as doc36,
16950
+ getDoc as getDoc38,
16951
+ getDocs as getDocs35,
16952
+ query as query35,
16953
+ updateDoc as updateDoc34,
16954
+ where as where35
16955
+ } from "firebase/firestore";
16956
+
16957
+ // src/backoffice/types/subcategory.types.ts
16958
+ var SUBCATEGORIES_COLLECTION = "subcategories";
16959
+
16960
+ // src/backoffice/services/subcategory.service.ts
16961
+ var SubcategoryService = class extends BaseService {
16962
+ /**
16963
+ * Vraća referencu na Firestore kolekciju podkategorija za određenu kategoriju
16964
+ * @param categoryId - ID roditeljske kategorije
16965
+ */
16966
+ getSubcategoriesRef(categoryId) {
16967
+ return collection35(
16968
+ this.db,
16969
+ CATEGORIES_COLLECTION,
16970
+ categoryId,
16971
+ SUBCATEGORIES_COLLECTION
16972
+ );
16973
+ }
16974
+ /**
16975
+ * Kreira novu podkategoriju u okviru kategorije
16976
+ * @param categoryId - ID kategorije kojoj će pripadati nova podkategorija
16977
+ * @param subcategory - Podaci za novu podkategoriju
16978
+ * @returns Kreirana podkategorija sa generisanim ID-em
16979
+ */
16980
+ async create(categoryId, subcategory) {
16981
+ const now = /* @__PURE__ */ new Date();
16982
+ const newSubcategory = {
16983
+ ...subcategory,
16984
+ categoryId,
16985
+ createdAt: now,
16986
+ updatedAt: now,
16987
+ isActive: true
16988
+ };
16989
+ const docRef = await addDoc7(
16990
+ this.getSubcategoriesRef(categoryId),
16991
+ newSubcategory
16992
+ );
16993
+ return { id: docRef.id, ...newSubcategory };
16994
+ }
16995
+ /**
16996
+ * Vraća sve aktivne podkategorije za određenu kategoriju
16997
+ * @param categoryId - ID kategorije čije podkategorije tražimo
16998
+ * @returns Lista aktivnih podkategorija
16999
+ */
17000
+ async getAllByCategoryId(categoryId) {
17001
+ const q = query35(
17002
+ this.getSubcategoriesRef(categoryId),
17003
+ where35("isActive", "==", true)
17004
+ );
17005
+ const snapshot = await getDocs35(q);
17006
+ return snapshot.docs.map(
17007
+ (doc38) => ({
17008
+ id: doc38.id,
17009
+ ...doc38.data()
17010
+ })
17011
+ );
17012
+ }
17013
+ /**
17014
+ * Ažurira postojeću podkategoriju
17015
+ * @param categoryId - ID kategorije kojoj pripada podkategorija
17016
+ * @param subcategoryId - ID podkategorije koja se ažurira
17017
+ * @param subcategory - Novi podaci za podkategoriju
17018
+ * @returns Ažurirana podkategorija
17019
+ */
17020
+ async update(categoryId, subcategoryId, subcategory) {
17021
+ const updateData = {
17022
+ ...subcategory,
17023
+ updatedAt: /* @__PURE__ */ new Date()
17024
+ };
17025
+ const docRef = doc36(this.getSubcategoriesRef(categoryId), subcategoryId);
17026
+ await updateDoc34(docRef, updateData);
17027
+ return this.getById(categoryId, subcategoryId);
17028
+ }
17029
+ /**
17030
+ * Soft delete podkategorije (postavlja isActive na false)
17031
+ * @param categoryId - ID kategorije kojoj pripada podkategorija
17032
+ * @param subcategoryId - ID podkategorije koja se briše
17033
+ */
17034
+ async delete(categoryId, subcategoryId) {
17035
+ await this.update(categoryId, subcategoryId, { isActive: false });
17036
+ }
17037
+ /**
17038
+ * Vraća podkategoriju po ID-u
17039
+ * @param categoryId - ID kategorije kojoj pripada podkategorija
17040
+ * @param subcategoryId - ID tražene podkategorije
17041
+ * @returns Podkategorija ili null ako ne postoji
17042
+ */
17043
+ async getById(categoryId, subcategoryId) {
17044
+ const docRef = doc36(this.getSubcategoriesRef(categoryId), subcategoryId);
17045
+ const docSnap = await getDoc38(docRef);
17046
+ if (!docSnap.exists()) return null;
17047
+ return {
17048
+ id: docSnap.id,
17049
+ ...docSnap.data()
17050
+ };
17051
+ }
17052
+ };
17053
+
17054
+ // src/backoffice/services/technology.service.ts
17055
+ import {
17056
+ addDoc as addDoc8,
17057
+ collection as collection36,
17058
+ doc as doc37,
17059
+ getDoc as getDoc39,
17060
+ getDocs as getDocs36,
17061
+ query as query36,
17062
+ updateDoc as updateDoc35,
17063
+ where as where36,
17064
+ arrayUnion as arrayUnion9,
17065
+ arrayRemove as arrayRemove8
17066
+ } from "firebase/firestore";
17067
+ var DEFAULT_CERTIFICATION_REQUIREMENT = {
17068
+ minimumLevel: "aesthetician" /* AESTHETICIAN */,
17069
+ requiredSpecialties: []
17070
+ };
17071
+ var TechnologyService = class extends BaseService {
17072
+ /**
17073
+ * Vraća referencu na Firestore kolekciju tehnologija
17074
+ */
17075
+ getTechnologiesRef() {
17076
+ return collection36(this.db, TECHNOLOGIES_COLLECTION);
17077
+ }
17078
+ /**
17079
+ * Kreira novu tehnologiju
17080
+ * @param technology - Podaci za novu tehnologiju
17081
+ * @returns Kreirana tehnologija sa generisanim ID-em
17082
+ */
17083
+ async create(technology) {
17084
+ const now = /* @__PURE__ */ new Date();
17085
+ const newTechnology = {
17086
+ ...technology,
17087
+ createdAt: now,
17088
+ updatedAt: now,
17089
+ isActive: true,
17090
+ requirements: technology.requirements || {
17091
+ pre: [],
17092
+ post: []
17093
+ },
17094
+ blockingConditions: technology.blockingConditions || [],
17095
+ contraindications: technology.contraindications || [],
17096
+ benefits: technology.benefits || [],
17097
+ certificationRequirement: technology.certificationRequirement || DEFAULT_CERTIFICATION_REQUIREMENT
17098
+ };
17099
+ const docRef = await addDoc8(this.getTechnologiesRef(), newTechnology);
17100
+ return { id: docRef.id, ...newTechnology };
17101
+ }
17102
+ /**
17103
+ * Vraća sve aktivne tehnologije
17104
+ * @returns Lista aktivnih tehnologija
17105
+ */
17106
+ async getAll() {
17107
+ const q = query36(this.getTechnologiesRef(), where36("isActive", "==", true));
17108
+ const snapshot = await getDocs36(q);
17109
+ return snapshot.docs.map(
17110
+ (doc38) => ({
17111
+ id: doc38.id,
17112
+ ...doc38.data()
17113
+ })
17114
+ );
17115
+ }
17116
+ /**
17117
+ * Vraća sve aktivne tehnologije za određenu familiju
17118
+ * @param family - Familija procedura
17119
+ * @returns Lista aktivnih tehnologija
17120
+ */
17121
+ async getAllByFamily(family) {
17122
+ const q = query36(
17123
+ this.getTechnologiesRef(),
17124
+ where36("isActive", "==", true),
17125
+ where36("family", "==", family)
17126
+ );
17127
+ const snapshot = await getDocs36(q);
17128
+ return snapshot.docs.map(
17129
+ (doc38) => ({
17130
+ id: doc38.id,
17131
+ ...doc38.data()
17132
+ })
17133
+ );
17134
+ }
17135
+ /**
17136
+ * Vraća sve aktivne tehnologije za određenu kategoriju
17137
+ * @param categoryId - ID kategorije
17138
+ * @returns Lista aktivnih tehnologija
17139
+ */
17140
+ async getAllByCategoryId(categoryId) {
17141
+ const q = query36(
17142
+ this.getTechnologiesRef(),
17143
+ where36("isActive", "==", true),
17144
+ where36("categoryId", "==", categoryId)
17145
+ );
17146
+ const snapshot = await getDocs36(q);
17147
+ return snapshot.docs.map(
17148
+ (doc38) => ({
17149
+ id: doc38.id,
17150
+ ...doc38.data()
17151
+ })
17152
+ );
17153
+ }
17154
+ /**
17155
+ * Vraća sve aktivne tehnologije za određenu podkategoriju
17156
+ * @param subcategoryId - ID podkategorije
17157
+ * @returns Lista aktivnih tehnologija
17158
+ */
17159
+ async getAllBySubcategoryId(subcategoryId) {
17160
+ const q = query36(
17161
+ this.getTechnologiesRef(),
17162
+ where36("isActive", "==", true),
17163
+ where36("subcategoryId", "==", subcategoryId)
17164
+ );
17165
+ const snapshot = await getDocs36(q);
17166
+ return snapshot.docs.map(
17167
+ (doc38) => ({
17168
+ id: doc38.id,
17169
+ ...doc38.data()
17170
+ })
17171
+ );
17172
+ }
17173
+ /**
17174
+ * Ažurira postojeću tehnologiju
17175
+ * @param technologyId - ID tehnologije
17176
+ * @param technology - Novi podaci za tehnologiju
17177
+ * @returns Ažurirana tehnologija
17178
+ */
17179
+ async update(technologyId, technology) {
17180
+ const updateData = {
17181
+ ...technology,
17182
+ updatedAt: /* @__PURE__ */ new Date()
17183
+ };
17184
+ const docRef = doc37(this.getTechnologiesRef(), technologyId);
17185
+ await updateDoc35(docRef, updateData);
17186
+ return this.getById(technologyId);
17187
+ }
17188
+ /**
17189
+ * Soft delete tehnologije (postavlja isActive na false)
17190
+ * @param technologyId - ID tehnologije koja se briše
17191
+ */
17192
+ async delete(technologyId) {
17193
+ await this.update(technologyId, {
17194
+ isActive: false
17195
+ });
17196
+ }
17197
+ /**
17198
+ * Vraća tehnologiju po ID-u
17199
+ * @param technologyId - ID tražene tehnologije
17200
+ * @returns Tehnologija ili null ako ne postoji
17201
+ */
17202
+ async getById(technologyId) {
17203
+ const docRef = doc37(this.getTechnologiesRef(), technologyId);
17204
+ const docSnap = await getDoc39(docRef);
17205
+ if (!docSnap.exists()) return null;
17206
+ return {
17207
+ id: docSnap.id,
17208
+ ...docSnap.data()
17209
+ };
17210
+ }
17211
+ /**
17212
+ * Dodaje novi zahtev tehnologiji
17213
+ * @param technologyId - ID tehnologije
17214
+ * @param requirement - Zahtev koji se dodaje
17215
+ * @returns Ažurirana tehnologija sa novim zahtevom
17216
+ */
17217
+ async addRequirement(technologyId, requirement) {
17218
+ const docRef = doc37(this.getTechnologiesRef(), technologyId);
17219
+ const requirementType = requirement.type === "pre" ? "requirements.pre" : "requirements.post";
17220
+ await updateDoc35(docRef, {
17221
+ [requirementType]: arrayUnion9(requirement),
17222
+ updatedAt: /* @__PURE__ */ new Date()
17223
+ });
17224
+ return this.getById(technologyId);
17225
+ }
17226
+ /**
17227
+ * Uklanja zahtev iz tehnologije
17228
+ * @param technologyId - ID tehnologije
17229
+ * @param requirement - Zahtev koji se uklanja
17230
+ * @returns Ažurirana tehnologija bez uklonjenog zahteva
17231
+ */
17232
+ async removeRequirement(technologyId, requirement) {
17233
+ const docRef = doc37(this.getTechnologiesRef(), technologyId);
17234
+ const requirementType = requirement.type === "pre" ? "requirements.pre" : "requirements.post";
17235
+ await updateDoc35(docRef, {
17236
+ [requirementType]: arrayRemove8(requirement),
17237
+ updatedAt: /* @__PURE__ */ new Date()
17238
+ });
17239
+ return this.getById(technologyId);
17240
+ }
17241
+ /**
17242
+ * Vraća sve zahteve za tehnologiju
17243
+ * @param technologyId - ID tehnologije
17244
+ * @param type - Opcioni filter za tip zahteva (pre/post)
17245
+ * @returns Lista zahteva
17246
+ */
17247
+ async getRequirements(technologyId, type) {
17248
+ const technology = await this.getById(technologyId);
17249
+ if (!technology || !technology.requirements) return [];
17250
+ if (type) {
17251
+ return technology.requirements[type];
17252
+ }
17253
+ return [...technology.requirements.pre, ...technology.requirements.post];
17254
+ }
17255
+ /**
17256
+ * Ažurira postojeći zahtev
17257
+ * @param technologyId - ID tehnologije
17258
+ * @param oldRequirement - Stari zahtev koji se menja
17259
+ * @param newRequirement - Novi zahtev koji zamenjuje stari
17260
+ * @returns Ažurirana tehnologija
17261
+ */
17262
+ async updateRequirement(technologyId, oldRequirement, newRequirement) {
17263
+ await this.removeRequirement(technologyId, oldRequirement);
17264
+ return this.addRequirement(technologyId, newRequirement);
17265
+ }
17266
+ /**
17267
+ * Dodaje blokirajući uslov tehnologiji
17268
+ * @param technologyId - ID tehnologije
17269
+ * @param condition - Blokirajući uslov koji se dodaje
17270
+ * @returns Ažurirana tehnologija
17271
+ */
17272
+ async addBlockingCondition(technologyId, condition) {
17273
+ const docRef = doc37(this.getTechnologiesRef(), technologyId);
17274
+ await updateDoc35(docRef, {
17275
+ blockingConditions: arrayUnion9(condition),
17276
+ updatedAt: /* @__PURE__ */ new Date()
17277
+ });
17278
+ return this.getById(technologyId);
17279
+ }
17280
+ /**
17281
+ * Uklanja blokirajući uslov iz tehnologije
17282
+ * @param technologyId - ID tehnologije
17283
+ * @param condition - Blokirajući uslov koji se uklanja
17284
+ * @returns Ažurirana tehnologija
17285
+ */
17286
+ async removeBlockingCondition(technologyId, condition) {
17287
+ const docRef = doc37(this.getTechnologiesRef(), technologyId);
17288
+ await updateDoc35(docRef, {
17289
+ blockingConditions: arrayRemove8(condition),
17290
+ updatedAt: /* @__PURE__ */ new Date()
17291
+ });
17292
+ return this.getById(technologyId);
17293
+ }
17294
+ /**
17295
+ * Dodaje kontraindikaciju tehnologiji
17296
+ * @param technologyId - ID tehnologije
17297
+ * @param contraindication - Kontraindikacija koja se dodaje
17298
+ * @returns Ažurirana tehnologija
17299
+ */
17300
+ async addContraindication(technologyId, contraindication) {
17301
+ const docRef = doc37(this.getTechnologiesRef(), technologyId);
17302
+ await updateDoc35(docRef, {
17303
+ contraindications: arrayUnion9(contraindication),
17304
+ updatedAt: /* @__PURE__ */ new Date()
17305
+ });
17306
+ return this.getById(technologyId);
17307
+ }
17308
+ /**
17309
+ * Uklanja kontraindikaciju iz tehnologije
17310
+ * @param technologyId - ID tehnologije
17311
+ * @param contraindication - Kontraindikacija koja se uklanja
17312
+ * @returns Ažurirana tehnologija
17313
+ */
17314
+ async removeContraindication(technologyId, contraindication) {
17315
+ const docRef = doc37(this.getTechnologiesRef(), technologyId);
17316
+ await updateDoc35(docRef, {
17317
+ contraindications: arrayRemove8(contraindication),
17318
+ updatedAt: /* @__PURE__ */ new Date()
17319
+ });
17320
+ return this.getById(technologyId);
17321
+ }
17322
+ /**
17323
+ * Dodaje benefit tehnologiji
17324
+ * @param technologyId - ID tehnologije
17325
+ * @param benefit - Benefit koji se dodaje
17326
+ * @returns Ažurirana tehnologija
17327
+ */
17328
+ async addBenefit(technologyId, benefit) {
17329
+ const docRef = doc37(this.getTechnologiesRef(), technologyId);
17330
+ await updateDoc35(docRef, {
17331
+ benefits: arrayUnion9(benefit),
17332
+ updatedAt: /* @__PURE__ */ new Date()
17333
+ });
17334
+ return this.getById(technologyId);
17335
+ }
17336
+ /**
17337
+ * Uklanja benefit iz tehnologije
17338
+ * @param technologyId - ID tehnologije
17339
+ * @param benefit - Benefit koji se uklanja
17340
+ * @returns Ažurirana tehnologija
17341
+ */
17342
+ async removeBenefit(technologyId, benefit) {
17343
+ const docRef = doc37(this.getTechnologiesRef(), technologyId);
17344
+ await updateDoc35(docRef, {
17345
+ benefits: arrayRemove8(benefit),
17346
+ updatedAt: /* @__PURE__ */ new Date()
17347
+ });
17348
+ return this.getById(technologyId);
17349
+ }
17350
+ /**
17351
+ * Vraća sve blokirajuće uslove za tehnologiju
17352
+ * @param technologyId - ID tehnologije
17353
+ * @returns Lista blokirajućih uslova
17354
+ */
17355
+ async getBlockingConditions(technologyId) {
17356
+ const technology = await this.getById(technologyId);
17357
+ return (technology == null ? void 0 : technology.blockingConditions) || [];
17358
+ }
17359
+ /**
17360
+ * Vraća sve kontraindikacije za tehnologiju
17361
+ * @param technologyId - ID tehnologije
17362
+ * @returns Lista kontraindikacija
17363
+ */
17364
+ async getContraindications(technologyId) {
17365
+ const technology = await this.getById(technologyId);
17366
+ return (technology == null ? void 0 : technology.contraindications) || [];
17367
+ }
17368
+ /**
17369
+ * Vraća sve benefite za tehnologiju
17370
+ * @param technologyId - ID tehnologije
17371
+ * @returns Lista benefita
17372
+ */
17373
+ async getBenefits(technologyId) {
17374
+ const technology = await this.getById(technologyId);
17375
+ return (technology == null ? void 0 : technology.benefits) || [];
17376
+ }
17377
+ /**
17378
+ * Ažurira zahteve sertifikacije za tehnologiju
17379
+ * @param technologyId - ID tehnologije
17380
+ * @param certificationRequirement - Novi zahtevi sertifikacije
17381
+ * @returns Ažurirana tehnologija
17382
+ */
17383
+ async updateCertificationRequirement(technologyId, certificationRequirement) {
17384
+ const docRef = doc37(this.getTechnologiesRef(), technologyId);
17385
+ await updateDoc35(docRef, {
17386
+ certificationRequirement,
17387
+ updatedAt: /* @__PURE__ */ new Date()
17388
+ });
17389
+ return this.getById(technologyId);
17390
+ }
17391
+ /**
17392
+ * Vraća zahteve sertifikacije za tehnologiju
17393
+ * @param technologyId - ID tehnologije
17394
+ * @returns Zahtevi sertifikacije ili null ako tehnologija ne postoji
17395
+ */
17396
+ async getCertificationRequirement(technologyId) {
17397
+ const technology = await this.getById(technologyId);
17398
+ return (technology == null ? void 0 : technology.certificationRequirement) || null;
17399
+ }
17400
+ /**
17401
+ * Proverava da li doktor ima odgovarajuću sertifikaciju za izvođenje tehnologije
17402
+ *
17403
+ * @param requiredCertification - Zahtevana sertifikacija za tehnologiju
17404
+ * @param practitionerCertification - Sertifikacija zdravstvenog radnika
17405
+ * @returns true ako zdravstveni radnik ima odgovarajuću sertifikaciju, false ako nema
17406
+ *
17407
+ * @example
17408
+ * const isValid = technologyService.validateCertification(
17409
+ * {
17410
+ * minimumLevel: CertificationLevel.DOCTOR,
17411
+ * requiredSpecialties: [CertificationSpecialty.INJECTABLES]
17412
+ * },
17413
+ * {
17414
+ * level: CertificationLevel.SPECIALIST,
17415
+ * specialties: [CertificationSpecialty.INJECTABLES, CertificationSpecialty.LASER]
17416
+ * }
17417
+ * );
17418
+ */
17419
+ validateCertification(requiredCertification, practitionerCertification) {
17420
+ const doctorLevel = Object.values(CertificationLevel).indexOf(
17421
+ practitionerCertification.level
17422
+ );
17423
+ const requiredLevel = Object.values(CertificationLevel).indexOf(
17424
+ requiredCertification.minimumLevel
17425
+ );
17426
+ if (doctorLevel < requiredLevel) return false;
17427
+ const requiredSpecialties = requiredCertification.requiredSpecialties || [];
17428
+ if (requiredSpecialties.length > 0) {
17429
+ const doctorSpecialties = practitionerCertification.specialties;
17430
+ const hasAllRequiredSpecialties = requiredSpecialties.every(
17431
+ (requiredSpecialty) => doctorSpecialties.includes(requiredSpecialty)
17432
+ );
17433
+ if (!hasAllRequiredSpecialties) return false;
17434
+ }
17435
+ return true;
17436
+ }
17437
+ /**
17438
+ * Vraća sve tehnologije koje je zdravstveni radnik sertifikovan da izvodi
17439
+ * zajedno sa listama dozvoljenih familija, kategorija i podkategorija
17440
+ *
17441
+ * @param practitioner - Profil zdravstvenog radnika
17442
+ * @returns Objekat koji sadrži:
17443
+ * - technologies: Lista tehnologija koje zdravstveni radnik može da izvodi
17444
+ * - families: Lista familija procedura koje zdravstveni radnik može da izvodi
17445
+ * - categories: Lista ID-eva kategorija koje zdravstveni radnik može da izvodi
17446
+ * - subcategories: Lista ID-eva podkategorija koje zdravstveni radnik može da izvodi
17447
+ *
17448
+ * @example
17449
+ * const practitioner = {
17450
+ * certification: {
17451
+ * level: CertificationLevel.DOCTOR,
17452
+ * specialties: [CertificationSpecialty.INJECTABLES]
17453
+ * }
17454
+ * };
17455
+ * const allowedTechnologies = await technologyService.getAllowedTechnologies(practitioner);
17456
+ * console.log(allowedTechnologies.families); // [ProcedureFamily.AESTHETICS]
17457
+ * console.log(allowedTechnologies.categories); // ["category1", "category2"]
17458
+ * console.log(allowedTechnologies.subcategories); // ["subcategory1", "subcategory2"]
17459
+ */
17460
+ async getAllowedTechnologies(practitioner) {
17461
+ const allTechnologies = await this.getAll();
17462
+ const allowedTechnologies = allTechnologies.filter(
17463
+ (technology) => this.validateCertification(
17464
+ technology.certificationRequirement,
17465
+ practitioner.certification
17466
+ )
17467
+ );
17468
+ const families = [...new Set(allowedTechnologies.map((t) => t.family))];
17469
+ const categories = [
17470
+ ...new Set(allowedTechnologies.map((t) => t.categoryId))
17471
+ ];
17472
+ const subcategories = [
17473
+ ...new Set(allowedTechnologies.map((t) => t.subcategoryId))
17474
+ ];
17475
+ return {
17476
+ technologies: allowedTechnologies,
17477
+ families,
17478
+ categories,
17479
+ subcategories
17480
+ };
17481
+ }
17482
+ };
17483
+
17484
+ // src/backoffice/constants/certification.constants.ts
17485
+ var DEFAULT_CERTIFICATION_REQUIREMENT2 = {
17486
+ minimumLevel: "aesthetician" /* AESTHETICIAN */,
17487
+ requiredSpecialties: []
17488
+ };
17489
+
17490
+ // src/backoffice/errors/backoffice.errors.ts
17491
+ var BackofficeError = class extends Error {
17492
+ constructor(message) {
17493
+ super(message);
17494
+ this.name = "BackofficeError";
17495
+ }
17496
+ };
17497
+ var CategoryError = class extends BackofficeError {
17498
+ constructor(message) {
17499
+ super(message);
17500
+ this.name = "CategoryError";
17501
+ }
17502
+ };
17503
+ var CategoryNotFoundError = class extends CategoryError {
17504
+ constructor(id) {
17505
+ super(`Kategorija sa ID-em ${id} nije prona\u0111ena`);
17506
+ this.name = "CategoryNotFoundError";
17507
+ }
17508
+ };
17509
+ var InvalidCategoryDataError = class extends CategoryError {
17510
+ constructor(message) {
17511
+ super(`Neva\u017Ee\u0107i podaci za kategoriju: ${message}`);
17512
+ this.name = "InvalidCategoryDataError";
17513
+ }
17514
+ };
17515
+ var SubcategoryError = class extends BackofficeError {
17516
+ constructor(message) {
17517
+ super(message);
17518
+ this.name = "SubcategoryError";
17519
+ }
17520
+ };
17521
+ var SubcategoryNotFoundError = class extends SubcategoryError {
17522
+ constructor(id) {
17523
+ super(`Podkategorija sa ID-em ${id} nije prona\u0111ena`);
17524
+ this.name = "SubcategoryNotFoundError";
17525
+ }
17526
+ };
17527
+ var InvalidSubcategoryDataError = class extends SubcategoryError {
17528
+ constructor(message) {
17529
+ super(`Neva\u017Ee\u0107i podaci za podkategoriju: ${message}`);
17530
+ this.name = "InvalidSubcategoryDataError";
17531
+ }
17532
+ };
17533
+ var TechnologyError = class extends BackofficeError {
17534
+ constructor(message) {
17535
+ super(message);
17536
+ this.name = "TechnologyError";
17537
+ }
17538
+ };
17539
+ var TechnologyNotFoundError = class extends TechnologyError {
17540
+ constructor(id) {
17541
+ super(`Tehnologija sa ID-em ${id} nije prona\u0111ena`);
17542
+ this.name = "TechnologyNotFoundError";
17543
+ }
17544
+ };
17545
+ var InvalidTechnologyDataError = class extends TechnologyError {
17546
+ constructor(message) {
17547
+ super(`Neva\u017Ee\u0107i podaci za tehnologiju: ${message}`);
17548
+ this.name = "InvalidTechnologyDataError";
17549
+ }
17550
+ };
17551
+ var RequirementError = class extends BackofficeError {
17552
+ constructor(message) {
17553
+ super(message);
17554
+ this.name = "RequirementError";
17555
+ }
17556
+ };
17557
+ var RequirementNotFoundError = class extends RequirementError {
17558
+ constructor(id) {
17559
+ super(`Zahtev sa ID-em ${id} nije prona\u0111en`);
17560
+ this.name = "RequirementNotFoundError";
17561
+ }
17562
+ };
17563
+ var InvalidRequirementDataError = class extends RequirementError {
17564
+ constructor(message) {
17565
+ super(`Neva\u017Ee\u0107i podaci za zahtev: ${message}`);
17566
+ this.name = "InvalidRequirementDataError";
17567
+ }
17568
+ };
17569
+ var InvalidTimeframeError = class extends RequirementError {
17570
+ constructor(message) {
17571
+ super(`Invalid timeframe: ${message}`);
17572
+ this.name = "InvalidTimeframeError";
17573
+ }
17574
+ };
17575
+ var RelationshipError = class extends BackofficeError {
17576
+ constructor(message) {
17577
+ super(message);
17578
+ this.name = "RelationshipError";
17579
+ }
17580
+ };
17581
+ var InvalidHierarchyError = class extends RelationshipError {
17582
+ constructor(message) {
17583
+ super(`Invalid hierarchy: ${message}`);
17584
+ this.name = "InvalidHierarchyError";
17585
+ }
17586
+ };
17587
+ var CircularReferenceError = class extends RelationshipError {
17588
+ constructor(message) {
17589
+ super(`Circular reference detected: ${message}`);
17590
+ this.name = "CircularReferenceError";
17591
+ }
17592
+ };
17593
+ var BlockingConditionError = class extends BackofficeError {
17594
+ constructor(message) {
17595
+ super(message);
17596
+ this.name = "BlockingConditionError";
17597
+ }
17598
+ };
17599
+ var InvalidBlockingConditionError = class extends BlockingConditionError {
17600
+ constructor(condition) {
17601
+ super(`Neva\u017Ee\u0107i blokiraju\u0107i uslov: ${condition}`);
17602
+ this.name = "InvalidBlockingConditionError";
17603
+ }
17604
+ };
17605
+ var ContraindicationError = class extends BackofficeError {
17606
+ constructor(message) {
17607
+ super(message);
17608
+ this.name = "ContraindicationError";
17609
+ }
17610
+ };
17611
+ var InvalidContraindicationError = class extends ContraindicationError {
17612
+ constructor(contraindication) {
17613
+ super(`Neva\u017Ee\u0107a kontraindikacija: ${contraindication}`);
17614
+ this.name = "InvalidContraindicationError";
17615
+ }
17616
+ };
17617
+ var TreatmentBenefitError = class extends BackofficeError {
17618
+ constructor(message) {
17619
+ super(message);
17620
+ this.name = "TreatmentBenefitError";
17621
+ }
17622
+ };
17623
+ var InvalidTreatmentBenefitError = class extends TreatmentBenefitError {
17624
+ constructor(benefit) {
17625
+ super(`Neva\u017Ee\u0107i benefit tretmana: ${benefit}`);
17626
+ this.name = "InvalidTreatmentBenefitError";
17627
+ }
17628
+ };
16424
17629
  export {
16425
17630
  APPOINTMENTS_COLLECTION,
16426
17631
  AdminTokenStatus,
@@ -16428,8 +17633,14 @@ export {
16428
17633
  AppointmentService,
16429
17634
  AppointmentStatus,
16430
17635
  AuthService,
17636
+ BRANDS_COLLECTION,
17637
+ BackofficeError,
16431
17638
  BaseService,
17639
+ BlockingCondition,
17640
+ BlockingConditionError,
17641
+ BrandService,
16432
17642
  CALENDAR_COLLECTION,
17643
+ CATEGORIES_COLLECTION,
16433
17644
  CLINICS_COLLECTION,
16434
17645
  CLINIC_ADMINS_COLLECTION,
16435
17646
  CLINIC_GROUPS_COLLECTION,
@@ -16438,17 +17649,28 @@ export {
16438
17649
  CalendarServiceV2,
16439
17650
  CalendarServiceV3,
16440
17651
  CalendarSyncStatus,
17652
+ CategoryError,
17653
+ CategoryNotFoundError,
17654
+ CategoryService,
17655
+ CertificationLevel,
17656
+ CertificationSpecialty,
17657
+ CircularReferenceError,
16441
17658
  ClinicAdminService,
16442
17659
  ClinicGroupService,
16443
17660
  ClinicPhotoTag,
16444
17661
  ClinicService,
16445
17662
  ClinicTag,
17663
+ Contraindication,
17664
+ ContraindicationError,
16446
17665
  CosmeticAllergySubtype,
17666
+ Currency,
17667
+ DEFAULT_CERTIFICATION_REQUIREMENT2 as DEFAULT_CERTIFICATION_REQUIREMENT,
16447
17668
  DEFAULT_MEDICAL_INFO,
16448
17669
  DOCTOR_FORMS_SUBCOLLECTION,
16449
17670
  DOCUMENTATION_TEMPLATES_COLLECTION,
16450
17671
  DocumentElementType,
16451
17672
  DocumentationTemplateService,
17673
+ DocumentationTemplateServiceBackoffice,
16452
17674
  DynamicVariable,
16453
17675
  EnvironmentalAllergySubtype,
16454
17676
  ExternalCalendarService,
@@ -16459,6 +17681,15 @@ export {
16459
17681
  Gender,
16460
17682
  HeadingLevel,
16461
17683
  INVITE_TOKENS_COLLECTION,
17684
+ InvalidBlockingConditionError,
17685
+ InvalidCategoryDataError,
17686
+ InvalidContraindicationError,
17687
+ InvalidHierarchyError,
17688
+ InvalidRequirementDataError,
17689
+ InvalidSubcategoryDataError,
17690
+ InvalidTechnologyDataError,
17691
+ InvalidTimeframeError,
17692
+ InvalidTreatmentBenefitError,
16462
17693
  Language,
16463
17694
  ListType,
16464
17695
  MEDIA_METADATA_COLLECTION,
@@ -16480,6 +17711,7 @@ export {
16480
17711
  PRACTITIONERS_COLLECTION,
16481
17712
  PRACTITIONER_INVITES_COLLECTION,
16482
17713
  PROCEDURES_COLLECTION,
17714
+ PRODUCTS_COLLECTION,
16483
17715
  PatientInstructionStatus,
16484
17716
  PatientRequirementOverallStatus,
16485
17717
  PatientRequirementsService,
@@ -16492,15 +17724,35 @@ export {
16492
17724
  PractitionerService,
16493
17725
  PractitionerStatus,
16494
17726
  PractitionerTokenStatus,
17727
+ PricingMeasure,
17728
+ ProcedureFamily,
16495
17729
  ProcedureService,
17730
+ ProductService,
16496
17731
  REGISTER_TOKENS_COLLECTION,
17732
+ REQUIREMENTS_COLLECTION,
16497
17733
  REVIEWS_COLLECTION,
17734
+ RelationshipError,
17735
+ RequirementError,
17736
+ RequirementNotFoundError,
17737
+ RequirementService,
17738
+ RequirementType,
16498
17739
  ReviewService,
17740
+ SUBCATEGORIES_COLLECTION,
16499
17741
  SYNCED_CALENDARS_COLLECTION,
16500
17742
  SearchLocationEnum,
17743
+ SubcategoryError,
17744
+ SubcategoryNotFoundError,
17745
+ SubcategoryService,
16501
17746
  SubscriptionModel,
16502
17747
  SyncedCalendarProvider,
17748
+ TECHNOLOGIES_COLLECTION,
17749
+ TechnologyError,
17750
+ TechnologyNotFoundError,
17751
+ TechnologyService,
17752
+ TimeUnit,
16503
17753
  TimestampUtils,
17754
+ TreatmentBenefit,
17755
+ TreatmentBenefitError,
16504
17756
  USERS_COLLECTION,
16505
17757
  USER_FORMS_SUBCOLLECTION,
16506
17758
  UserRole,
@@ -16523,9 +17775,15 @@ export {
16523
17775
  beforeAfterPerZoneSchema,
16524
17776
  billingPerZoneSchema,
16525
17777
  blockingConditionSchema,
17778
+ blockingConditionSchemaBackoffice,
16526
17779
  buildPractitionerData,
16527
17780
  calendarEventSchema,
16528
17781
  calendarEventTimeSchema,
17782
+ categorySchema,
17783
+ categoryUpdateSchema,
17784
+ certificationLevelSchema,
17785
+ certificationRequirementSchema,
17786
+ certificationSpecialtySchema,
16529
17787
  checkEmailExists,
16530
17788
  cleanupFirebaseUser,
16531
17789
  clinicAdminOptionsSchema,
@@ -16544,6 +17802,7 @@ export {
16544
17802
  clinicTagsSchema,
16545
17803
  contactPersonSchema,
16546
17804
  contraindicationSchema,
17805
+ contraindicationSchemaBackoffice,
16547
17806
  createAdminTokenSchema,
16548
17807
  createAppointmentSchema,
16549
17808
  createBlockingEventSchema,
@@ -16626,6 +17885,7 @@ export {
16626
17885
  preRequirementNotificationSchema,
16627
17886
  procedureCategorizationSchema,
16628
17887
  procedureExtendedInfoSchema,
17888
+ procedureFamilySchemaBackoffice,
16629
17889
  procedureInfoSchema,
16630
17890
  procedureReviewInfoSchema,
16631
17891
  procedureReviewSchema,
@@ -16634,15 +17894,26 @@ export {
16634
17894
  requesterInfoSchema,
16635
17895
  requirementImportanceSchema,
16636
17896
  requirementInstructionDueNotificationSchema,
17897
+ requirementSchema,
17898
+ requirementTypeSchema,
17899
+ requirementUpdateSchema,
16637
17900
  rescheduleAppointmentSchema,
16638
17901
  reviewSchema,
16639
17902
  searchAppointmentsSchema,
16640
17903
  searchPatientsSchema,
16641
17904
  sharedClinicContactInfoSchema,
16642
17905
  sharedClinicLocationSchema,
17906
+ subcategorySchema,
17907
+ subcategoryUpdateSchema,
16643
17908
  syncedCalendarEventSchema,
17909
+ technologyRequirementsSchema,
17910
+ technologySchema,
17911
+ technologyUpdateSchema,
16644
17912
  timeSlotSchema2 as timeSlotSchema,
17913
+ timeUnitSchemaBackoffice,
17914
+ timeframeSchema,
16645
17915
  timestampSchema,
17916
+ treatmentBenefitSchemaBackoffice,
16646
17917
  updateAllergySchema,
16647
17918
  updateAppointmentSchema,
16648
17919
  updateBlockingConditionSchema,