@blackcode_sa/metaestetics-api 1.12.67 → 1.12.69

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.
@@ -2053,6 +2053,7 @@ declare enum NotificationType {
2053
2053
  FORM_REMINDER = "formReminder",// Reminds user to fill a specific form
2054
2054
  FORM_SUBMISSION_CONFIRMATION = "formSubmissionConfirmation",// Confirms form was submitted
2055
2055
  REVIEW_REQUEST = "reviewRequest",// Request for patient review post-appointment
2056
+ PROCEDURE_RECOMMENDATION = "procedureRecommendation",// Doctor recommended a procedure for follow-up
2056
2057
  PAYMENT_DUE = "paymentDue",
2057
2058
  PAYMENT_CONFIRMATION = "paymentConfirmation",
2058
2059
  PAYMENT_FAILED = "paymentFailed",
@@ -2222,6 +2223,24 @@ interface ReviewRequestNotification extends BaseNotification {
2222
2223
  practitionerName?: string;
2223
2224
  procedureName?: string;
2224
2225
  }
2226
+ /**
2227
+ * Notification for when a doctor recommends a procedure for follow-up.
2228
+ * Example: "Dr. Smith recommended [Procedure Name] for you. Suggested timeframe: in 2 weeks"
2229
+ */
2230
+ interface ProcedureRecommendationNotification extends BaseNotification {
2231
+ notificationType: NotificationType.PROCEDURE_RECOMMENDATION;
2232
+ appointmentId: string;
2233
+ recommendationId: string;
2234
+ procedureId: string;
2235
+ procedureName: string;
2236
+ practitionerName: string;
2237
+ clinicName: string;
2238
+ note?: string;
2239
+ timeframe: {
2240
+ value: number;
2241
+ unit: 'day' | 'week' | 'month' | 'year';
2242
+ };
2243
+ }
2225
2244
  /**
2226
2245
  * Generic notification for direct messages or announcements.
2227
2246
  */
@@ -2237,7 +2256,7 @@ interface PaymentConfirmationNotification extends BaseNotification {
2237
2256
  /**
2238
2257
  * Unija svih tipova notifikacija
2239
2258
  */
2240
- type Notification = PreRequirementNotification | PostRequirementNotification | RequirementInstructionDueNotification | AppointmentReminderNotification | AppointmentStatusChangeNotification | AppointmentRescheduledProposalNotification | AppointmentCancelledNotification | FormReminderNotification | FormSubmissionConfirmationNotification | ReviewRequestNotification | GeneralMessageNotification | PaymentConfirmationNotification;
2259
+ type Notification = PreRequirementNotification | PostRequirementNotification | RequirementInstructionDueNotification | AppointmentReminderNotification | AppointmentStatusChangeNotification | AppointmentRescheduledProposalNotification | AppointmentCancelledNotification | FormReminderNotification | FormSubmissionConfirmationNotification | ReviewRequestNotification | ProcedureRecommendationNotification | GeneralMessageNotification | PaymentConfirmationNotification;
2241
2260
 
2242
2261
  /**
2243
2262
  * Minimal interface for the new mailgun.js client's messages API
@@ -2676,6 +2695,20 @@ declare class AppointmentAggregationService {
2676
2695
  * @param after - The appointment state after update
2677
2696
  */
2678
2697
  private handleZonePhotosUpdate;
2698
+ /**
2699
+ * Checks if recommended procedures have changed between two appointment states
2700
+ * @param before - The appointment state before update
2701
+ * @param after - The appointment state after update
2702
+ * @returns True if recommendations have changed, false otherwise
2703
+ */
2704
+ private hasRecommendationsChanged;
2705
+ /**
2706
+ * Handles recommended procedures update - creates notifications for newly added recommendations
2707
+ * @param before - The appointment state before update
2708
+ * @param after - The appointment state after update
2709
+ * @param patientProfile - The patient profile (for expo tokens)
2710
+ */
2711
+ private handleRecommendedProceduresUpdate;
2679
2712
  }
2680
2713
 
2681
2714
  /**
@@ -2053,6 +2053,7 @@ declare enum NotificationType {
2053
2053
  FORM_REMINDER = "formReminder",// Reminds user to fill a specific form
2054
2054
  FORM_SUBMISSION_CONFIRMATION = "formSubmissionConfirmation",// Confirms form was submitted
2055
2055
  REVIEW_REQUEST = "reviewRequest",// Request for patient review post-appointment
2056
+ PROCEDURE_RECOMMENDATION = "procedureRecommendation",// Doctor recommended a procedure for follow-up
2056
2057
  PAYMENT_DUE = "paymentDue",
2057
2058
  PAYMENT_CONFIRMATION = "paymentConfirmation",
2058
2059
  PAYMENT_FAILED = "paymentFailed",
@@ -2222,6 +2223,24 @@ interface ReviewRequestNotification extends BaseNotification {
2222
2223
  practitionerName?: string;
2223
2224
  procedureName?: string;
2224
2225
  }
2226
+ /**
2227
+ * Notification for when a doctor recommends a procedure for follow-up.
2228
+ * Example: "Dr. Smith recommended [Procedure Name] for you. Suggested timeframe: in 2 weeks"
2229
+ */
2230
+ interface ProcedureRecommendationNotification extends BaseNotification {
2231
+ notificationType: NotificationType.PROCEDURE_RECOMMENDATION;
2232
+ appointmentId: string;
2233
+ recommendationId: string;
2234
+ procedureId: string;
2235
+ procedureName: string;
2236
+ practitionerName: string;
2237
+ clinicName: string;
2238
+ note?: string;
2239
+ timeframe: {
2240
+ value: number;
2241
+ unit: 'day' | 'week' | 'month' | 'year';
2242
+ };
2243
+ }
2225
2244
  /**
2226
2245
  * Generic notification for direct messages or announcements.
2227
2246
  */
@@ -2237,7 +2256,7 @@ interface PaymentConfirmationNotification extends BaseNotification {
2237
2256
  /**
2238
2257
  * Unija svih tipova notifikacija
2239
2258
  */
2240
- type Notification = PreRequirementNotification | PostRequirementNotification | RequirementInstructionDueNotification | AppointmentReminderNotification | AppointmentStatusChangeNotification | AppointmentRescheduledProposalNotification | AppointmentCancelledNotification | FormReminderNotification | FormSubmissionConfirmationNotification | ReviewRequestNotification | GeneralMessageNotification | PaymentConfirmationNotification;
2259
+ type Notification = PreRequirementNotification | PostRequirementNotification | RequirementInstructionDueNotification | AppointmentReminderNotification | AppointmentStatusChangeNotification | AppointmentRescheduledProposalNotification | AppointmentCancelledNotification | FormReminderNotification | FormSubmissionConfirmationNotification | ReviewRequestNotification | ProcedureRecommendationNotification | GeneralMessageNotification | PaymentConfirmationNotification;
2241
2260
 
2242
2261
  /**
2243
2262
  * Minimal interface for the new mailgun.js client's messages API
@@ -2676,6 +2695,20 @@ declare class AppointmentAggregationService {
2676
2695
  * @param after - The appointment state after update
2677
2696
  */
2678
2697
  private handleZonePhotosUpdate;
2698
+ /**
2699
+ * Checks if recommended procedures have changed between two appointment states
2700
+ * @param before - The appointment state before update
2701
+ * @param after - The appointment state after update
2702
+ * @returns True if recommendations have changed, false otherwise
2703
+ */
2704
+ private hasRecommendationsChanged;
2705
+ /**
2706
+ * Handles recommended procedures update - creates notifications for newly added recommendations
2707
+ * @param before - The appointment state before update
2708
+ * @param after - The appointment state after update
2709
+ * @param patientProfile - The patient profile (for expo tokens)
2710
+ */
2711
+ private handleRecommendedProceduresUpdate;
2679
2712
  }
2680
2713
 
2681
2714
  /**
@@ -489,6 +489,7 @@ var NotificationType = /* @__PURE__ */ ((NotificationType2) => {
489
489
  NotificationType2["FORM_REMINDER"] = "formReminder";
490
490
  NotificationType2["FORM_SUBMISSION_CONFIRMATION"] = "formSubmissionConfirmation";
491
491
  NotificationType2["REVIEW_REQUEST"] = "reviewRequest";
492
+ NotificationType2["PROCEDURE_RECOMMENDATION"] = "procedureRecommendation";
492
493
  NotificationType2["PAYMENT_DUE"] = "paymentDue";
493
494
  NotificationType2["PAYMENT_CONFIRMATION"] = "paymentConfirmation";
494
495
  NotificationType2["PAYMENT_FAILED"] = "paymentFailed";
@@ -2928,6 +2929,11 @@ var AppointmentAggregationService = class {
2928
2929
  Logger.info(`[AggService] Zone photos changed for appointment ${after.id}`);
2929
2930
  await this.handleZonePhotosUpdate(before, after);
2930
2931
  }
2932
+ const recommendationsChanged = this.hasRecommendationsChanged(before, after);
2933
+ if (recommendationsChanged) {
2934
+ Logger.info(`[AggService] Recommended procedures changed for appointment ${after.id}`);
2935
+ await this.handleRecommendedProceduresUpdate(before, after, patientProfile);
2936
+ }
2931
2937
  Logger.info(`[AggService] Successfully processed UPDATE for appointment: ${after.id}`);
2932
2938
  } catch (error) {
2933
2939
  Logger.error(
@@ -3960,6 +3966,104 @@ var AppointmentAggregationService = class {
3960
3966
  );
3961
3967
  }
3962
3968
  }
3969
+ /**
3970
+ * Checks if recommended procedures have changed between two appointment states
3971
+ * @param before - The appointment state before update
3972
+ * @param after - The appointment state after update
3973
+ * @returns True if recommendations have changed, false otherwise
3974
+ */
3975
+ hasRecommendationsChanged(before, after) {
3976
+ var _a, _b;
3977
+ const beforeRecommendations = ((_a = before.metadata) == null ? void 0 : _a.recommendedProcedures) || [];
3978
+ const afterRecommendations = ((_b = after.metadata) == null ? void 0 : _b.recommendedProcedures) || [];
3979
+ if (beforeRecommendations.length !== afterRecommendations.length) {
3980
+ return true;
3981
+ }
3982
+ for (let i = 0; i < afterRecommendations.length; i++) {
3983
+ const beforeRec = beforeRecommendations[i];
3984
+ const afterRec = afterRecommendations[i];
3985
+ if (!beforeRec || !afterRec) {
3986
+ return true;
3987
+ }
3988
+ if (beforeRec.procedure.procedureId !== afterRec.procedure.procedureId || beforeRec.note !== afterRec.note || beforeRec.timeframe.value !== afterRec.timeframe.value || beforeRec.timeframe.unit !== afterRec.timeframe.unit) {
3989
+ return true;
3990
+ }
3991
+ }
3992
+ return false;
3993
+ }
3994
+ /**
3995
+ * Handles recommended procedures update - creates notifications for newly added recommendations
3996
+ * @param before - The appointment state before update
3997
+ * @param after - The appointment state after update
3998
+ * @param patientProfile - The patient profile (for expo tokens)
3999
+ */
4000
+ async handleRecommendedProceduresUpdate(before, after, patientProfile) {
4001
+ var _a, _b, _c, _d, _e;
4002
+ try {
4003
+ const beforeRecommendations = ((_a = before.metadata) == null ? void 0 : _a.recommendedProcedures) || [];
4004
+ const afterRecommendations = ((_b = after.metadata) == null ? void 0 : _b.recommendedProcedures) || [];
4005
+ const newRecommendations = afterRecommendations.slice(beforeRecommendations.length);
4006
+ if (newRecommendations.length === 0) {
4007
+ Logger.info(
4008
+ `[AggService] No new recommendations detected for appointment ${after.id}`
4009
+ );
4010
+ return;
4011
+ }
4012
+ Logger.info(
4013
+ `[AggService] Found ${newRecommendations.length} new recommendation(s) for appointment ${after.id}`
4014
+ );
4015
+ for (let i = 0; i < newRecommendations.length; i++) {
4016
+ const recommendation = newRecommendations[i];
4017
+ const recommendationIndex = beforeRecommendations.length + i;
4018
+ const recommendationId = `${after.id}:${recommendationIndex}`;
4019
+ const timeframeText = `${recommendation.timeframe.value} ${recommendation.timeframe.unit}${recommendation.timeframe.value > 1 ? "s" : ""}`;
4020
+ const notificationPayload = {
4021
+ userId: after.patientId,
4022
+ userRole: "patient" /* PATIENT */,
4023
+ notificationType: "procedureRecommendation" /* PROCEDURE_RECOMMENDATION */,
4024
+ notificationTime: admin6.firestore.Timestamp.now(),
4025
+ notificationTokens: (patientProfile == null ? void 0 : patientProfile.expoTokens) || [],
4026
+ title: "New Procedure Recommendation",
4027
+ body: `${((_c = after.practitionerInfo) == null ? void 0 : _c.name) || "Your doctor"} recommended "${recommendation.procedure.procedureName}" for you. Suggested timeframe: in ${timeframeText}`,
4028
+ appointmentId: after.id,
4029
+ recommendationId,
4030
+ procedureId: recommendation.procedure.procedureId,
4031
+ procedureName: recommendation.procedure.procedureName,
4032
+ practitionerName: ((_d = after.practitionerInfo) == null ? void 0 : _d.name) || "Unknown Practitioner",
4033
+ clinicName: ((_e = after.clinicInfo) == null ? void 0 : _e.name) || "Unknown Clinic",
4034
+ note: recommendation.note,
4035
+ timeframe: recommendation.timeframe
4036
+ };
4037
+ try {
4038
+ const notificationId = await this.notificationsAdmin.createNotification(
4039
+ notificationPayload
4040
+ );
4041
+ Logger.info(
4042
+ `[AggService] Created notification ${notificationId} for recommendation ${recommendationId}`
4043
+ );
4044
+ if ((patientProfile == null ? void 0 : patientProfile.expoTokens) && patientProfile.expoTokens.length > 0) {
4045
+ const notification = await this.notificationsAdmin.getNotification(notificationId);
4046
+ if (notification) {
4047
+ await this.notificationsAdmin.sendPushNotification(notification);
4048
+ Logger.info(
4049
+ `[AggService] Sent push notification for recommendation ${recommendationId}`
4050
+ );
4051
+ }
4052
+ }
4053
+ } catch (error) {
4054
+ Logger.error(
4055
+ `[AggService] Error creating notification for recommendation ${recommendationId}:`,
4056
+ error
4057
+ );
4058
+ }
4059
+ }
4060
+ } catch (error) {
4061
+ Logger.error(
4062
+ `[AggService] Error handling recommended procedures update for appointment ${after.id}:`,
4063
+ error
4064
+ );
4065
+ }
4066
+ }
3963
4067
  };
3964
4068
 
3965
4069
  // src/admin/aggregation/clinic/clinic.aggregation.service.ts
@@ -427,6 +427,7 @@ var NotificationType = /* @__PURE__ */ ((NotificationType2) => {
427
427
  NotificationType2["FORM_REMINDER"] = "formReminder";
428
428
  NotificationType2["FORM_SUBMISSION_CONFIRMATION"] = "formSubmissionConfirmation";
429
429
  NotificationType2["REVIEW_REQUEST"] = "reviewRequest";
430
+ NotificationType2["PROCEDURE_RECOMMENDATION"] = "procedureRecommendation";
430
431
  NotificationType2["PAYMENT_DUE"] = "paymentDue";
431
432
  NotificationType2["PAYMENT_CONFIRMATION"] = "paymentConfirmation";
432
433
  NotificationType2["PAYMENT_FAILED"] = "paymentFailed";
@@ -2866,6 +2867,11 @@ var AppointmentAggregationService = class {
2866
2867
  Logger.info(`[AggService] Zone photos changed for appointment ${after.id}`);
2867
2868
  await this.handleZonePhotosUpdate(before, after);
2868
2869
  }
2870
+ const recommendationsChanged = this.hasRecommendationsChanged(before, after);
2871
+ if (recommendationsChanged) {
2872
+ Logger.info(`[AggService] Recommended procedures changed for appointment ${after.id}`);
2873
+ await this.handleRecommendedProceduresUpdate(before, after, patientProfile);
2874
+ }
2869
2875
  Logger.info(`[AggService] Successfully processed UPDATE for appointment: ${after.id}`);
2870
2876
  } catch (error) {
2871
2877
  Logger.error(
@@ -3898,6 +3904,104 @@ var AppointmentAggregationService = class {
3898
3904
  );
3899
3905
  }
3900
3906
  }
3907
+ /**
3908
+ * Checks if recommended procedures have changed between two appointment states
3909
+ * @param before - The appointment state before update
3910
+ * @param after - The appointment state after update
3911
+ * @returns True if recommendations have changed, false otherwise
3912
+ */
3913
+ hasRecommendationsChanged(before, after) {
3914
+ var _a, _b;
3915
+ const beforeRecommendations = ((_a = before.metadata) == null ? void 0 : _a.recommendedProcedures) || [];
3916
+ const afterRecommendations = ((_b = after.metadata) == null ? void 0 : _b.recommendedProcedures) || [];
3917
+ if (beforeRecommendations.length !== afterRecommendations.length) {
3918
+ return true;
3919
+ }
3920
+ for (let i = 0; i < afterRecommendations.length; i++) {
3921
+ const beforeRec = beforeRecommendations[i];
3922
+ const afterRec = afterRecommendations[i];
3923
+ if (!beforeRec || !afterRec) {
3924
+ return true;
3925
+ }
3926
+ if (beforeRec.procedure.procedureId !== afterRec.procedure.procedureId || beforeRec.note !== afterRec.note || beforeRec.timeframe.value !== afterRec.timeframe.value || beforeRec.timeframe.unit !== afterRec.timeframe.unit) {
3927
+ return true;
3928
+ }
3929
+ }
3930
+ return false;
3931
+ }
3932
+ /**
3933
+ * Handles recommended procedures update - creates notifications for newly added recommendations
3934
+ * @param before - The appointment state before update
3935
+ * @param after - The appointment state after update
3936
+ * @param patientProfile - The patient profile (for expo tokens)
3937
+ */
3938
+ async handleRecommendedProceduresUpdate(before, after, patientProfile) {
3939
+ var _a, _b, _c, _d, _e;
3940
+ try {
3941
+ const beforeRecommendations = ((_a = before.metadata) == null ? void 0 : _a.recommendedProcedures) || [];
3942
+ const afterRecommendations = ((_b = after.metadata) == null ? void 0 : _b.recommendedProcedures) || [];
3943
+ const newRecommendations = afterRecommendations.slice(beforeRecommendations.length);
3944
+ if (newRecommendations.length === 0) {
3945
+ Logger.info(
3946
+ `[AggService] No new recommendations detected for appointment ${after.id}`
3947
+ );
3948
+ return;
3949
+ }
3950
+ Logger.info(
3951
+ `[AggService] Found ${newRecommendations.length} new recommendation(s) for appointment ${after.id}`
3952
+ );
3953
+ for (let i = 0; i < newRecommendations.length; i++) {
3954
+ const recommendation = newRecommendations[i];
3955
+ const recommendationIndex = beforeRecommendations.length + i;
3956
+ const recommendationId = `${after.id}:${recommendationIndex}`;
3957
+ const timeframeText = `${recommendation.timeframe.value} ${recommendation.timeframe.unit}${recommendation.timeframe.value > 1 ? "s" : ""}`;
3958
+ const notificationPayload = {
3959
+ userId: after.patientId,
3960
+ userRole: "patient" /* PATIENT */,
3961
+ notificationType: "procedureRecommendation" /* PROCEDURE_RECOMMENDATION */,
3962
+ notificationTime: admin6.firestore.Timestamp.now(),
3963
+ notificationTokens: (patientProfile == null ? void 0 : patientProfile.expoTokens) || [],
3964
+ title: "New Procedure Recommendation",
3965
+ body: `${((_c = after.practitionerInfo) == null ? void 0 : _c.name) || "Your doctor"} recommended "${recommendation.procedure.procedureName}" for you. Suggested timeframe: in ${timeframeText}`,
3966
+ appointmentId: after.id,
3967
+ recommendationId,
3968
+ procedureId: recommendation.procedure.procedureId,
3969
+ procedureName: recommendation.procedure.procedureName,
3970
+ practitionerName: ((_d = after.practitionerInfo) == null ? void 0 : _d.name) || "Unknown Practitioner",
3971
+ clinicName: ((_e = after.clinicInfo) == null ? void 0 : _e.name) || "Unknown Clinic",
3972
+ note: recommendation.note,
3973
+ timeframe: recommendation.timeframe
3974
+ };
3975
+ try {
3976
+ const notificationId = await this.notificationsAdmin.createNotification(
3977
+ notificationPayload
3978
+ );
3979
+ Logger.info(
3980
+ `[AggService] Created notification ${notificationId} for recommendation ${recommendationId}`
3981
+ );
3982
+ if ((patientProfile == null ? void 0 : patientProfile.expoTokens) && patientProfile.expoTokens.length > 0) {
3983
+ const notification = await this.notificationsAdmin.getNotification(notificationId);
3984
+ if (notification) {
3985
+ await this.notificationsAdmin.sendPushNotification(notification);
3986
+ Logger.info(
3987
+ `[AggService] Sent push notification for recommendation ${recommendationId}`
3988
+ );
3989
+ }
3990
+ }
3991
+ } catch (error) {
3992
+ Logger.error(
3993
+ `[AggService] Error creating notification for recommendation ${recommendationId}:`,
3994
+ error
3995
+ );
3996
+ }
3997
+ }
3998
+ } catch (error) {
3999
+ Logger.error(
4000
+ `[AggService] Error handling recommended procedures update for appointment ${after.id}:`,
4001
+ error
4002
+ );
4003
+ }
4004
+ }
3901
4005
  };
3902
4006
 
3903
4007
  // src/admin/aggregation/clinic/clinic.aggregation.service.ts
@@ -209,6 +209,12 @@ interface ICategoryService {
209
209
  * });
210
210
  */
211
211
  declare class CategoryService extends BaseService implements ICategoryService {
212
+ /**
213
+ * Filters out excluded categories from a list.
214
+ * @param categories - List of categories to filter
215
+ * @returns Filtered list without excluded categories
216
+ */
217
+ private filterExcludedCategories;
212
218
  /**
213
219
  * Referenca na Firestore kolekciju kategorija
214
220
  */
@@ -294,6 +300,13 @@ declare class CategoryService extends BaseService implements ICategoryService {
294
300
  * @returns Kategorija ili null ako ne postoji
295
301
  */
296
302
  getById(id: string): Promise<Category | null>;
303
+ /**
304
+ * Internal method to get category by ID without filtering.
305
+ * Used internally for consultation procedures.
306
+ * @param id - ID of the category to get
307
+ * @returns Category or null if not found
308
+ */
309
+ getByIdInternal(id: string): Promise<Category | null>;
297
310
  /**
298
311
  * Finds a category by exact name match within a specific family.
299
312
  * Used for CSV import matching.
@@ -1900,6 +1913,12 @@ declare class RequirementService extends BaseService {
1900
1913
  * });
1901
1914
  */
1902
1915
  declare class SubcategoryService extends BaseService {
1916
+ /**
1917
+ * Filters out excluded subcategories from a list.
1918
+ * @param subcategories - List of subcategories to filter
1919
+ * @returns Filtered list without excluded subcategories
1920
+ */
1921
+ private filterExcludedSubcategories;
1903
1922
  /**
1904
1923
  * Vraća referencu na Firestore kolekciju podkategorija za određenu kategoriju
1905
1924
  * @param categoryId - ID roditeljske kategorije
@@ -1994,6 +2013,14 @@ declare class SubcategoryService extends BaseService {
1994
2013
  * @returns Podkategorija ili null ako ne postoji
1995
2014
  */
1996
2015
  getById(categoryId: string, subcategoryId: string): Promise<Subcategory | null>;
2016
+ /**
2017
+ * Internal method to get subcategory by ID without filtering.
2018
+ * Used internally for consultation procedures.
2019
+ * @param categoryId - ID of the category
2020
+ * @param subcategoryId - ID of the subcategory to get
2021
+ * @returns Subcategory or null if not found
2022
+ */
2023
+ getByIdInternal(categoryId: string, subcategoryId: string): Promise<Subcategory | null>;
1997
2024
  /**
1998
2025
  * Finds a subcategory by exact name match within a specific category.
1999
2026
  * Used for CSV import matching.
@@ -2020,6 +2047,12 @@ declare class SubcategoryService extends BaseService {
2020
2047
  * Service for managing technologies.
2021
2048
  */
2022
2049
  declare class TechnologyService extends BaseService implements ITechnologyService {
2050
+ /**
2051
+ * Filters out excluded technologies from a list.
2052
+ * @param technologies - List of technologies to filter
2053
+ * @returns Filtered list without excluded technologies
2054
+ */
2055
+ private filterExcludedTechnologies;
2023
2056
  /**
2024
2057
  * Reference to the Firestore collection of technologies.
2025
2058
  */
@@ -2127,6 +2160,13 @@ declare class TechnologyService extends BaseService implements ITechnologyServic
2127
2160
  * @returns The technology or null if it doesn't exist.
2128
2161
  */
2129
2162
  getById(id: string): Promise<Technology | null>;
2163
+ /**
2164
+ * Internal method to get technology by ID without filtering.
2165
+ * Used internally for consultation procedures.
2166
+ * @param id - The ID of the requested technology
2167
+ * @returns The technology or null if it doesn't exist
2168
+ */
2169
+ getByIdInternal(id: string): Promise<Technology | null>;
2130
2170
  /**
2131
2171
  * Finds a technology by exact name match.
2132
2172
  * Used for CSV import duplicate detection.
@@ -209,6 +209,12 @@ interface ICategoryService {
209
209
  * });
210
210
  */
211
211
  declare class CategoryService extends BaseService implements ICategoryService {
212
+ /**
213
+ * Filters out excluded categories from a list.
214
+ * @param categories - List of categories to filter
215
+ * @returns Filtered list without excluded categories
216
+ */
217
+ private filterExcludedCategories;
212
218
  /**
213
219
  * Referenca na Firestore kolekciju kategorija
214
220
  */
@@ -294,6 +300,13 @@ declare class CategoryService extends BaseService implements ICategoryService {
294
300
  * @returns Kategorija ili null ako ne postoji
295
301
  */
296
302
  getById(id: string): Promise<Category | null>;
303
+ /**
304
+ * Internal method to get category by ID without filtering.
305
+ * Used internally for consultation procedures.
306
+ * @param id - ID of the category to get
307
+ * @returns Category or null if not found
308
+ */
309
+ getByIdInternal(id: string): Promise<Category | null>;
297
310
  /**
298
311
  * Finds a category by exact name match within a specific family.
299
312
  * Used for CSV import matching.
@@ -1900,6 +1913,12 @@ declare class RequirementService extends BaseService {
1900
1913
  * });
1901
1914
  */
1902
1915
  declare class SubcategoryService extends BaseService {
1916
+ /**
1917
+ * Filters out excluded subcategories from a list.
1918
+ * @param subcategories - List of subcategories to filter
1919
+ * @returns Filtered list without excluded subcategories
1920
+ */
1921
+ private filterExcludedSubcategories;
1903
1922
  /**
1904
1923
  * Vraća referencu na Firestore kolekciju podkategorija za određenu kategoriju
1905
1924
  * @param categoryId - ID roditeljske kategorije
@@ -1994,6 +2013,14 @@ declare class SubcategoryService extends BaseService {
1994
2013
  * @returns Podkategorija ili null ako ne postoji
1995
2014
  */
1996
2015
  getById(categoryId: string, subcategoryId: string): Promise<Subcategory | null>;
2016
+ /**
2017
+ * Internal method to get subcategory by ID without filtering.
2018
+ * Used internally for consultation procedures.
2019
+ * @param categoryId - ID of the category
2020
+ * @param subcategoryId - ID of the subcategory to get
2021
+ * @returns Subcategory or null if not found
2022
+ */
2023
+ getByIdInternal(categoryId: string, subcategoryId: string): Promise<Subcategory | null>;
1997
2024
  /**
1998
2025
  * Finds a subcategory by exact name match within a specific category.
1999
2026
  * Used for CSV import matching.
@@ -2020,6 +2047,12 @@ declare class SubcategoryService extends BaseService {
2020
2047
  * Service for managing technologies.
2021
2048
  */
2022
2049
  declare class TechnologyService extends BaseService implements ITechnologyService {
2050
+ /**
2051
+ * Filters out excluded technologies from a list.
2052
+ * @param technologies - List of technologies to filter
2053
+ * @returns Filtered list without excluded technologies
2054
+ */
2055
+ private filterExcludedTechnologies;
2023
2056
  /**
2024
2057
  * Reference to the Firestore collection of technologies.
2025
2058
  */
@@ -2127,6 +2160,13 @@ declare class TechnologyService extends BaseService implements ITechnologyServic
2127
2160
  * @returns The technology or null if it doesn't exist.
2128
2161
  */
2129
2162
  getById(id: string): Promise<Technology | null>;
2163
+ /**
2164
+ * Internal method to get technology by ID without filtering.
2165
+ * Used internally for consultation procedures.
2166
+ * @param id - The ID of the requested technology
2167
+ * @returns The technology or null if it doesn't exist
2168
+ */
2169
+ getByIdInternal(id: string): Promise<Technology | null>;
2130
2170
  /**
2131
2171
  * Finds a technology by exact name match.
2132
2172
  * Used for CSV import duplicate detection.