@blackcode_sa/metaestetics-api 1.15.14 → 1.15.17-staging.0

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.
Files changed (326) hide show
  1. package/dist/admin/index.d.mts +377 -222
  2. package/dist/admin/index.d.ts +377 -222
  3. package/dist/admin/index.js +625 -206
  4. package/dist/admin/index.mjs +624 -206
  5. package/dist/backoffice/index.d.mts +24 -0
  6. package/dist/backoffice/index.d.ts +24 -0
  7. package/dist/index.d.mts +297 -9
  8. package/dist/index.d.ts +297 -9
  9. package/dist/index.js +1144 -632
  10. package/dist/index.mjs +1139 -619
  11. package/package.json +2 -1
  12. package/src/__mocks__/firstore.ts +10 -10
  13. package/src/admin/aggregation/README.md +79 -79
  14. package/src/admin/aggregation/appointment/README.md +151 -129
  15. package/src/admin/aggregation/appointment/appointment.aggregation.service.ts +2137 -2091
  16. package/src/admin/aggregation/appointment/index.ts +1 -1
  17. package/src/admin/aggregation/clinic/README.md +52 -52
  18. package/src/admin/aggregation/clinic/clinic.aggregation.service.ts +966 -966
  19. package/src/admin/aggregation/clinic/index.ts +1 -1
  20. package/src/admin/aggregation/forms/README.md +13 -13
  21. package/src/admin/aggregation/forms/filled-forms.aggregation.service.ts +322 -322
  22. package/src/admin/aggregation/forms/index.ts +1 -1
  23. package/src/admin/aggregation/index.ts +8 -8
  24. package/src/admin/aggregation/patient/README.md +27 -27
  25. package/src/admin/aggregation/patient/index.ts +1 -1
  26. package/src/admin/aggregation/patient/patient.aggregation.service.ts +141 -141
  27. package/src/admin/aggregation/practitioner/README.md +42 -42
  28. package/src/admin/aggregation/practitioner/index.ts +1 -1
  29. package/src/admin/aggregation/practitioner/practitioner.aggregation.service.ts +433 -433
  30. package/src/admin/aggregation/practitioner-invite/index.ts +1 -1
  31. package/src/admin/aggregation/practitioner-invite/practitioner-invite.aggregation.service.ts +961 -961
  32. package/src/admin/aggregation/procedure/README.md +43 -43
  33. package/src/admin/aggregation/procedure/index.ts +1 -1
  34. package/src/admin/aggregation/procedure/procedure.aggregation.service.ts +702 -702
  35. package/src/admin/aggregation/reviews/index.ts +1 -1
  36. package/src/admin/aggregation/reviews/reviews.aggregation.service.ts +689 -689
  37. package/src/admin/analytics/analytics.admin.service.ts +278 -278
  38. package/src/admin/analytics/index.ts +2 -2
  39. package/src/admin/booking/README.md +184 -125
  40. package/src/admin/booking/booking.admin.ts +1330 -1073
  41. package/src/admin/booking/booking.calculator.ts +850 -712
  42. package/src/admin/booking/booking.types.ts +76 -59
  43. package/src/admin/booking/index.ts +3 -3
  44. package/src/admin/booking/timezones-problem.md +185 -185
  45. package/src/admin/calendar/README.md +62 -7
  46. package/src/admin/calendar/calendar.admin.service.ts +345 -345
  47. package/src/admin/calendar/index.ts +2 -1
  48. package/src/admin/calendar/resource-calendar.admin.ts +198 -0
  49. package/src/admin/documentation-templates/document-manager.admin.ts +260 -260
  50. package/src/admin/documentation-templates/index.ts +1 -1
  51. package/src/admin/free-consultation/free-consultation-utils.admin.ts +148 -148
  52. package/src/admin/free-consultation/index.ts +1 -1
  53. package/src/admin/index.ts +83 -83
  54. package/src/admin/logger/index.ts +78 -78
  55. package/src/admin/mailing/README.md +139 -139
  56. package/src/admin/mailing/appointment/appointment.mailing.service.ts +1253 -1253
  57. package/src/admin/mailing/appointment/index.ts +1 -1
  58. package/src/admin/mailing/appointment/templates/patient/appointment-confirmed.html +40 -40
  59. package/src/admin/mailing/base.mailing.service.ts +208 -208
  60. package/src/admin/mailing/clinicWelcome/clinicWelcome.mailing.ts +292 -292
  61. package/src/admin/mailing/clinicWelcome/index.ts +1 -1
  62. package/src/admin/mailing/clinicWelcome/templates/welcome.template.ts +225 -225
  63. package/src/admin/mailing/index.ts +5 -5
  64. package/src/admin/mailing/patientInvite/index.ts +2 -2
  65. package/src/admin/mailing/patientInvite/patientInvite.mailing.ts +415 -415
  66. package/src/admin/mailing/patientInvite/templates/invitation.template.ts +105 -105
  67. package/src/admin/mailing/practitionerInvite/existing-practitioner-invite.mailing.ts +611 -611
  68. package/src/admin/mailing/practitionerInvite/index.ts +2 -2
  69. package/src/admin/mailing/practitionerInvite/practitionerInvite.mailing.ts +395 -395
  70. package/src/admin/mailing/practitionerInvite/templates/existing-practitioner-invitation.template.ts +155 -155
  71. package/src/admin/mailing/practitionerInvite/templates/invitation.template.ts +101 -101
  72. package/src/admin/mailing/practitionerInvite/templates/invite-accepted-notification.template.ts +228 -228
  73. package/src/admin/mailing/practitionerInvite/templates/invite-rejected-notification.template.ts +242 -242
  74. package/src/admin/notifications/index.ts +1 -1
  75. package/src/admin/notifications/notifications.admin.ts +818 -818
  76. package/src/admin/requirements/README.md +128 -128
  77. package/src/admin/requirements/index.ts +1 -1
  78. package/src/admin/requirements/patient-requirements.admin.service.ts +475 -475
  79. package/src/admin/users/index.ts +1 -1
  80. package/src/admin/users/user-profile.admin.ts +405 -405
  81. package/src/backoffice/constants/certification.constants.ts +13 -13
  82. package/src/backoffice/constants/index.ts +1 -1
  83. package/src/backoffice/errors/backoffice.errors.ts +181 -181
  84. package/src/backoffice/errors/index.ts +1 -1
  85. package/src/backoffice/expo-safe/README.md +26 -26
  86. package/src/backoffice/expo-safe/index.ts +41 -41
  87. package/src/backoffice/index.ts +5 -5
  88. package/src/backoffice/services/FIXES_README.md +102 -102
  89. package/src/backoffice/services/README.md +57 -57
  90. package/src/backoffice/services/analytics.service.proposal.md +863 -863
  91. package/src/backoffice/services/analytics.service.summary.md +143 -143
  92. package/src/backoffice/services/brand.service.ts +260 -260
  93. package/src/backoffice/services/category.service.ts +384 -384
  94. package/src/backoffice/services/constants.service.ts +385 -385
  95. package/src/backoffice/services/documentation-template.service.ts +202 -202
  96. package/src/backoffice/services/index.ts +10 -10
  97. package/src/backoffice/services/migrate-products.ts +116 -116
  98. package/src/backoffice/services/product.service.ts +557 -557
  99. package/src/backoffice/services/requirement.service.ts +235 -235
  100. package/src/backoffice/services/subcategory.service.ts +461 -461
  101. package/src/backoffice/services/technology.service.ts +1153 -1153
  102. package/src/backoffice/types/README.md +12 -12
  103. package/src/backoffice/types/admin-constants.types.ts +69 -69
  104. package/src/backoffice/types/brand.types.ts +29 -29
  105. package/src/backoffice/types/category.types.ts +67 -67
  106. package/src/backoffice/types/documentation-templates.types.ts +28 -28
  107. package/src/backoffice/types/index.ts +10 -10
  108. package/src/backoffice/types/procedure-product.types.ts +38 -38
  109. package/src/backoffice/types/product.types.ts +239 -239
  110. package/src/backoffice/types/requirement.types.ts +63 -63
  111. package/src/backoffice/types/static/README.md +18 -18
  112. package/src/backoffice/types/static/blocking-condition.types.ts +21 -21
  113. package/src/backoffice/types/static/certification.types.ts +37 -37
  114. package/src/backoffice/types/static/contraindication.types.ts +19 -19
  115. package/src/backoffice/types/static/index.ts +6 -6
  116. package/src/backoffice/types/static/pricing.types.ts +16 -16
  117. package/src/backoffice/types/static/procedure-family.types.ts +14 -14
  118. package/src/backoffice/types/static/treatment-benefit.types.ts +22 -22
  119. package/src/backoffice/types/subcategory.types.ts +34 -34
  120. package/src/backoffice/types/technology.types.ts +168 -168
  121. package/src/backoffice/validations/index.ts +1 -1
  122. package/src/backoffice/validations/schemas.ts +164 -164
  123. package/src/config/__mocks__/firebase.ts +99 -99
  124. package/src/config/firebase.ts +78 -78
  125. package/src/config/index.ts +17 -17
  126. package/src/config/tiers.config.ts +255 -229
  127. package/src/errors/auth.error.ts +6 -6
  128. package/src/errors/auth.errors.ts +211 -211
  129. package/src/errors/clinic.errors.ts +32 -32
  130. package/src/errors/firebase.errors.ts +47 -47
  131. package/src/errors/user.errors.ts +99 -99
  132. package/src/index.backup.ts +407 -407
  133. package/src/index.ts +6 -6
  134. package/src/locales/en.ts +31 -31
  135. package/src/recommender/admin/index.ts +1 -1
  136. package/src/recommender/admin/services/recommender.service.admin.ts +5 -5
  137. package/src/recommender/front/index.ts +1 -1
  138. package/src/recommender/front/services/onboarding.service.ts +5 -5
  139. package/src/recommender/front/services/recommender.service.ts +3 -3
  140. package/src/recommender/index.ts +1 -1
  141. package/src/services/PATIENTAUTH.MD +197 -197
  142. package/src/services/README.md +106 -106
  143. package/src/services/__tests__/auth/auth.mock.test.ts +17 -17
  144. package/src/services/__tests__/auth/auth.setup.ts +298 -298
  145. package/src/services/__tests__/auth.service.test.ts +310 -310
  146. package/src/services/__tests__/base.service.test.ts +36 -36
  147. package/src/services/__tests__/user.service.test.ts +530 -530
  148. package/src/services/analytics/ARCHITECTURE.md +199 -199
  149. package/src/services/analytics/CLOUD_FUNCTIONS.md +225 -225
  150. package/src/services/analytics/GROUPED_ANALYTICS.md +501 -501
  151. package/src/services/analytics/QUICK_START.md +393 -393
  152. package/src/services/analytics/README.md +304 -304
  153. package/src/services/analytics/SUMMARY.md +141 -141
  154. package/src/services/analytics/TRENDS.md +380 -380
  155. package/src/services/analytics/USAGE_GUIDE.md +518 -518
  156. package/src/services/analytics/analytics-cloud.service.ts +222 -222
  157. package/src/services/analytics/analytics.service.ts +2148 -2148
  158. package/src/services/analytics/index.ts +4 -4
  159. package/src/services/analytics/review-analytics.service.ts +941 -941
  160. package/src/services/analytics/utils/appointment-filtering.utils.ts +138 -138
  161. package/src/services/analytics/utils/cost-calculation.utils.ts +182 -182
  162. package/src/services/analytics/utils/grouping.utils.ts +434 -434
  163. package/src/services/analytics/utils/stored-analytics.utils.ts +347 -347
  164. package/src/services/analytics/utils/time-calculation.utils.ts +186 -186
  165. package/src/services/analytics/utils/trend-calculation.utils.ts +200 -200
  166. package/src/services/appointment/README.md +17 -17
  167. package/src/services/appointment/appointment.service.ts +2943 -2941
  168. package/src/services/appointment/index.ts +1 -1
  169. package/src/services/appointment/utils/appointment.utils.ts +620 -620
  170. package/src/services/appointment/utils/extended-procedure.utils.ts +354 -354
  171. package/src/services/appointment/utils/form-initialization.utils.ts +516 -516
  172. package/src/services/appointment/utils/recommended-procedure.utils.ts +195 -195
  173. package/src/services/appointment/utils/zone-management.utils.ts +468 -468
  174. package/src/services/appointment/utils/zone-photo.utils.ts +302 -302
  175. package/src/services/auth/auth.service.ts +1435 -1435
  176. package/src/services/auth/auth.v2.service.ts +961 -961
  177. package/src/services/auth/index.ts +7 -7
  178. package/src/services/auth/utils/error.utils.ts +90 -90
  179. package/src/services/auth/utils/firebase.utils.ts +49 -49
  180. package/src/services/auth/utils/index.ts +21 -21
  181. package/src/services/auth/utils/practitioner.utils.ts +125 -125
  182. package/src/services/base.service.ts +41 -41
  183. package/src/services/calendar/calendar.service.ts +1077 -1077
  184. package/src/services/calendar/calendar.v2.service.ts +1693 -1693
  185. package/src/services/calendar/calendar.v3.service.ts +313 -313
  186. package/src/services/calendar/externalCalendar.service.ts +178 -178
  187. package/src/services/calendar/index.ts +5 -5
  188. package/src/services/calendar/synced-calendars.service.ts +743 -743
  189. package/src/services/calendar/utils/appointment.utils.ts +265 -265
  190. package/src/services/calendar/utils/calendar-event.utils.ts +676 -676
  191. package/src/services/calendar/utils/clinic.utils.ts +237 -237
  192. package/src/services/calendar/utils/docs.utils.ts +157 -157
  193. package/src/services/calendar/utils/google-calendar.utils.ts +697 -697
  194. package/src/services/calendar/utils/index.ts +8 -8
  195. package/src/services/calendar/utils/patient.utils.ts +198 -198
  196. package/src/services/calendar/utils/practitioner.utils.ts +221 -221
  197. package/src/services/calendar/utils/synced-calendar.utils.ts +472 -472
  198. package/src/services/clinic/README.md +204 -204
  199. package/src/services/clinic/__tests__/clinic-admin.service.test.ts +265 -265
  200. package/src/services/clinic/__tests__/clinic-group.service.test.ts +222 -222
  201. package/src/services/clinic/__tests__/clinic.service.test.ts +302 -302
  202. package/src/services/clinic/billing-transactions.service.ts +217 -217
  203. package/src/services/clinic/clinic-admin.service.ts +202 -202
  204. package/src/services/clinic/clinic-group.service.ts +310 -310
  205. package/src/services/clinic/clinic.service.ts +720 -720
  206. package/src/services/clinic/index.ts +5 -5
  207. package/src/services/clinic/practitioner-invite.service.ts +519 -519
  208. package/src/services/clinic/utils/admin.utils.ts +551 -551
  209. package/src/services/clinic/utils/clinic-group.utils.ts +646 -646
  210. package/src/services/clinic/utils/clinic.utils.ts +1023 -1023
  211. package/src/services/clinic/utils/filter.utils.d.ts +23 -23
  212. package/src/services/clinic/utils/filter.utils.ts +462 -462
  213. package/src/services/clinic/utils/index.ts +10 -10
  214. package/src/services/clinic/utils/photos.utils.ts +188 -188
  215. package/src/services/clinic/utils/search.utils.ts +83 -83
  216. package/src/services/clinic/utils/tag.utils.ts +124 -124
  217. package/src/services/documentation-templates/documentation-template.service.ts +537 -537
  218. package/src/services/documentation-templates/filled-document.service.ts +597 -597
  219. package/src/services/documentation-templates/index.ts +2 -2
  220. package/src/services/index.ts +16 -15
  221. package/src/services/media/index.ts +1 -1
  222. package/src/services/media/media.service.ts +418 -418
  223. package/src/services/notifications/__tests__/notification.service.test.ts +242 -242
  224. package/src/services/notifications/index.ts +1 -1
  225. package/src/services/notifications/notification.service.ts +215 -215
  226. package/src/services/patient/README.md +48 -48
  227. package/src/services/patient/To-Do.md +43 -43
  228. package/src/services/patient/__tests__/patient.service.test.ts +286 -286
  229. package/src/services/patient/index.ts +2 -2
  230. package/src/services/patient/patient.service.ts +1021 -1021
  231. package/src/services/patient/patientRequirements.service.ts +309 -309
  232. package/src/services/patient/utils/aesthetic-analysis.utils.ts +176 -176
  233. package/src/services/patient/utils/body-assessment.utils.ts +159 -159
  234. package/src/services/patient/utils/clinic.utils.ts +159 -159
  235. package/src/services/patient/utils/docs.utils.ts +142 -142
  236. package/src/services/patient/utils/hair-scalp-assessment.utils.ts +158 -158
  237. package/src/services/patient/utils/index.ts +9 -9
  238. package/src/services/patient/utils/location.utils.ts +126 -126
  239. package/src/services/patient/utils/medical-stuff.utils.ts +143 -143
  240. package/src/services/patient/utils/medical.utils.ts +458 -458
  241. package/src/services/patient/utils/practitioner.utils.ts +260 -260
  242. package/src/services/patient/utils/pre-surgical-assessment.utils.ts +161 -161
  243. package/src/services/patient/utils/profile.utils.ts +510 -510
  244. package/src/services/patient/utils/sensitive.utils.ts +260 -260
  245. package/src/services/patient/utils/skin-quality-assessment.utils.ts +160 -160
  246. package/src/services/patient/utils/token.utils.ts +211 -211
  247. package/src/services/practitioner/README.md +145 -145
  248. package/src/services/practitioner/index.ts +1 -1
  249. package/src/services/practitioner/practitioner.service.ts +2355 -2354
  250. package/src/services/procedure/README.md +163 -163
  251. package/src/services/procedure/index.ts +1 -1
  252. package/src/services/procedure/procedure.service.ts +2521 -2521
  253. package/src/services/resource/README.md +119 -0
  254. package/src/services/resource/index.ts +1 -0
  255. package/src/services/resource/resource.service.ts +555 -0
  256. package/src/services/reviews/index.ts +1 -1
  257. package/src/services/reviews/reviews.service.ts +745 -745
  258. package/src/services/tier-enforcement.ts +240 -240
  259. package/src/services/user/index.ts +1 -1
  260. package/src/services/user/user.service.ts +533 -533
  261. package/src/services/user/user.v2.service.ts +467 -467
  262. package/src/types/analytics/analytics.types.ts +597 -597
  263. package/src/types/analytics/grouped-analytics.types.ts +173 -173
  264. package/src/types/analytics/index.ts +4 -4
  265. package/src/types/analytics/stored-analytics.types.ts +137 -137
  266. package/src/types/appointment/index.ts +524 -517
  267. package/src/types/calendar/index.ts +261 -260
  268. package/src/types/calendar/synced-calendar.types.ts +66 -66
  269. package/src/types/clinic/index.ts +530 -529
  270. package/src/types/clinic/practitioner-invite.types.ts +91 -91
  271. package/src/types/clinic/preferences.types.ts +159 -159
  272. package/src/types/clinic/rbac.types.ts +64 -63
  273. package/src/types/clinic/to-do +3 -3
  274. package/src/types/documentation-templates/index.ts +308 -308
  275. package/src/types/index.ts +50 -47
  276. package/src/types/notifications/README.md +77 -77
  277. package/src/types/notifications/index.ts +300 -300
  278. package/src/types/patient/aesthetic-analysis.types.ts +66 -66
  279. package/src/types/patient/allergies.ts +58 -58
  280. package/src/types/patient/body-assessment.types.ts +93 -93
  281. package/src/types/patient/hair-scalp-assessment.types.ts +98 -98
  282. package/src/types/patient/index.ts +279 -279
  283. package/src/types/patient/medical-info.types.ts +152 -152
  284. package/src/types/patient/patient-requirements.ts +92 -92
  285. package/src/types/patient/pre-surgical-assessment.types.ts +95 -95
  286. package/src/types/patient/skin-quality-assessment.types.ts +105 -105
  287. package/src/types/patient/token.types.ts +61 -61
  288. package/src/types/practitioner/index.ts +208 -208
  289. package/src/types/procedure/index.ts +189 -183
  290. package/src/types/profile/index.ts +39 -39
  291. package/src/types/resource/README.md +153 -0
  292. package/src/types/resource/index.ts +199 -0
  293. package/src/types/reviews/index.ts +132 -132
  294. package/src/types/tz-lookup.d.ts +4 -4
  295. package/src/types/user/index.ts +60 -60
  296. package/src/utils/TIMESTAMPS.md +176 -176
  297. package/src/utils/TimestampUtils.ts +241 -241
  298. package/src/utils/index.ts +1 -1
  299. package/src/validations/README.md +94 -0
  300. package/src/validations/appointment.schema.ts +589 -589
  301. package/src/validations/calendar.schema.ts +225 -225
  302. package/src/validations/clinic.schema.ts +494 -494
  303. package/src/validations/common.schema.ts +25 -25
  304. package/src/validations/documentation-templates/index.ts +1 -1
  305. package/src/validations/documentation-templates/template.schema.ts +220 -220
  306. package/src/validations/documentation-templates.schema.ts +10 -10
  307. package/src/validations/index.ts +21 -20
  308. package/src/validations/media.schema.ts +10 -10
  309. package/src/validations/notification.schema.ts +90 -90
  310. package/src/validations/patient/aesthetic-analysis.schema.ts +55 -55
  311. package/src/validations/patient/body-assessment.schema.ts +82 -82
  312. package/src/validations/patient/hair-scalp-assessment.schema.ts +70 -70
  313. package/src/validations/patient/medical-info.schema.ts +177 -177
  314. package/src/validations/patient/patient-requirements.schema.ts +84 -84
  315. package/src/validations/patient/pre-surgical-assessment.schema.ts +78 -78
  316. package/src/validations/patient/skin-quality-assessment.schema.ts +70 -70
  317. package/src/validations/patient/token.schema.ts +29 -29
  318. package/src/validations/patient.schema.ts +217 -217
  319. package/src/validations/practitioner.schema.ts +224 -224
  320. package/src/validations/procedure-product.schema.ts +41 -41
  321. package/src/validations/procedure.schema.ts +136 -124
  322. package/src/validations/profile-info.schema.ts +41 -41
  323. package/src/validations/resource.schema.ts +57 -0
  324. package/src/validations/reviews.schema.ts +195 -195
  325. package/src/validations/schemas.ts +109 -109
  326. package/src/validations/shared.schema.ts +78 -78
@@ -262,6 +262,7 @@ __export(index_exports, {
262
262
  PractitionerTokenStatus: () => PractitionerTokenStatus,
263
263
  ProcedureAggregationService: () => ProcedureAggregationService,
264
264
  REVENUE_ANALYTICS_SUBCOLLECTION: () => REVENUE_ANALYTICS_SUBCOLLECTION,
265
+ ResourceCalendarAdminService: () => ResourceCalendarAdminService,
265
266
  ReviewsAggregationService: () => ReviewsAggregationService,
266
267
  SubscriptionStatus: () => SubscriptionStatus,
267
268
  TIME_EFFICIENCY_ANALYTICS_SUBCOLLECTION: () => TIME_EFFICIENCY_ANALYTICS_SUBCOLLECTION,
@@ -498,6 +499,7 @@ var BillingTransactionType = /* @__PURE__ */ ((BillingTransactionType2) => {
498
499
  BillingTransactionType2["SUBSCRIPTION_CANCELED"] = "subscription_canceled";
499
500
  BillingTransactionType2["SUBSCRIPTION_REACTIVATED"] = "subscription_reactivated";
500
501
  BillingTransactionType2["SUBSCRIPTION_DELETED"] = "subscription_deleted";
502
+ BillingTransactionType2["ADDON_PURCHASED"] = "addon_purchased";
501
503
  return BillingTransactionType2;
502
504
  })(BillingTransactionType || {});
503
505
 
@@ -601,7 +603,7 @@ var PatientRequirementOverallStatus = /* @__PURE__ */ ((PatientRequirementOveral
601
603
  var PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME = "patientRequirements";
602
604
 
603
605
  // src/admin/aggregation/appointment/appointment.aggregation.service.ts
604
- var admin6 = __toESM(require("firebase-admin"));
606
+ var admin7 = __toESM(require("firebase-admin"));
605
607
 
606
608
  // src/backoffice/types/requirement.types.ts
607
609
  var REQUIREMENTS_COLLECTION = "backoffice_requirements";
@@ -620,6 +622,11 @@ var DOCUMENTATION_TEMPLATES_COLLECTION = "documentation-templates";
620
622
  var USER_FORMS_SUBCOLLECTION = "user-forms";
621
623
  var DOCTOR_FORMS_SUBCOLLECTION = "doctor-forms";
622
624
 
625
+ // src/types/resource/index.ts
626
+ var RESOURCES_COLLECTION = "resources";
627
+ var RESOURCE_INSTANCES_SUBCOLLECTION = "instances";
628
+ var RESOURCE_CALENDAR_SUBCOLLECTION = "calendar";
629
+
623
630
  // src/types/reviews/index.ts
624
631
  var REVIEWS_COLLECTION = "reviews";
625
632
 
@@ -698,9 +705,9 @@ var Logger = class {
698
705
 
699
706
  // src/admin/notifications/notifications.admin.ts
700
707
  var NotificationsAdmin = class {
701
- constructor(firestore19) {
708
+ constructor(firestore20) {
702
709
  this.expo = new import_expo_server_sdk.Expo();
703
- this.db = firestore19 || admin2.firestore();
710
+ this.db = firestore20 || admin2.firestore();
704
711
  }
705
712
  /**
706
713
  * Dohvata notifikaciju po ID-u
@@ -1292,8 +1299,8 @@ var NotificationsAdmin = class {
1292
1299
 
1293
1300
  // src/admin/requirements/patient-requirements.admin.service.ts
1294
1301
  var PatientRequirementsAdminService = class {
1295
- constructor(firestore19) {
1296
- this.db = firestore19 || admin3.firestore();
1302
+ constructor(firestore20) {
1303
+ this.db = firestore20 || admin3.firestore();
1297
1304
  this.notificationsAdmin = new NotificationsAdmin(this.db);
1298
1305
  }
1299
1306
  /**
@@ -1621,8 +1628,8 @@ var PatientRequirementsAdminService = class {
1621
1628
  // src/admin/calendar/calendar.admin.service.ts
1622
1629
  var admin4 = __toESM(require("firebase-admin"));
1623
1630
  var CalendarAdminService = class {
1624
- constructor(firestore19) {
1625
- this.db = firestore19 || admin4.firestore();
1631
+ constructor(firestore20) {
1632
+ this.db = firestore20 || admin4.firestore();
1626
1633
  Logger.info("[CalendarAdminService] Initialized.");
1627
1634
  }
1628
1635
  /**
@@ -1896,11 +1903,163 @@ var CalendarAdminService = class {
1896
1903
  }
1897
1904
  };
1898
1905
 
1906
+ // src/admin/calendar/resource-calendar.admin.ts
1907
+ var admin5 = __toESM(require("firebase-admin"));
1908
+ var ResourceCalendarAdminService = class {
1909
+ constructor(firestore20) {
1910
+ this.db = firestore20 || admin5.firestore();
1911
+ Logger.info("[ResourceCalendarAdminService] Initialized.");
1912
+ }
1913
+ /**
1914
+ * Builds the Firestore document path for a resource calendar event.
1915
+ */
1916
+ getResourceCalendarEventPath(clinicBranchId, booking) {
1917
+ return `${CLINICS_COLLECTION}/${clinicBranchId}/${RESOURCES_COLLECTION}/${booking.resourceId}/${RESOURCE_INSTANCES_SUBCOLLECTION}/${booking.resourceInstanceId}/${RESOURCE_CALENDAR_SUBCOLLECTION}/${booking.calendarEventId}`;
1918
+ }
1919
+ /**
1920
+ * Updates the status of all resource calendar events associated with a given appointment.
1921
+ *
1922
+ * @param appointment - The appointment object containing resourceBookings.
1923
+ * @param newStatus - The new CalendarEventStatus to set.
1924
+ */
1925
+ async updateResourceBookingEventsStatus(appointment, newStatus) {
1926
+ const resourceBookings = appointment.resourceBookings;
1927
+ if (!resourceBookings || resourceBookings.length === 0) {
1928
+ Logger.debug(
1929
+ `[ResourceCalendarAdminService] No resource bookings on appointment ${appointment.id}, skipping status update.`
1930
+ );
1931
+ return;
1932
+ }
1933
+ Logger.info(
1934
+ `[ResourceCalendarAdminService] Updating ${resourceBookings.length} resource calendar event(s) to ${newStatus} for appointment ${appointment.id}`
1935
+ );
1936
+ const batch = this.db.batch();
1937
+ const serverTimestamp = admin5.firestore.FieldValue.serverTimestamp();
1938
+ for (const booking of resourceBookings) {
1939
+ const eventPath = this.getResourceCalendarEventPath(
1940
+ appointment.clinicBranchId,
1941
+ booking
1942
+ );
1943
+ const eventRef = this.db.doc(eventPath);
1944
+ batch.update(eventRef, {
1945
+ status: newStatus,
1946
+ updatedAt: serverTimestamp
1947
+ });
1948
+ Logger.debug(
1949
+ `[ResourceCalendarAdminService] Added status update for resource event ${booking.calendarEventId} (${booking.resourceName} / ${booking.resourceInstanceLabel})`
1950
+ );
1951
+ }
1952
+ try {
1953
+ await batch.commit();
1954
+ Logger.info(
1955
+ `[ResourceCalendarAdminService] Successfully updated ${resourceBookings.length} resource calendar event statuses for appointment ${appointment.id}.`
1956
+ );
1957
+ } catch (error) {
1958
+ Logger.error(
1959
+ `[ResourceCalendarAdminService] Error updating resource calendar event statuses for appointment ${appointment.id}:`,
1960
+ error
1961
+ );
1962
+ throw error;
1963
+ }
1964
+ }
1965
+ /**
1966
+ * Updates the eventTime (start and end) of all resource calendar events
1967
+ * associated with a given appointment.
1968
+ *
1969
+ * @param appointment - The appointment object containing resourceBookings.
1970
+ * @param newEventTime - The new event time with admin Timestamps.
1971
+ */
1972
+ async updateResourceBookingEventsTime(appointment, newEventTime) {
1973
+ const resourceBookings = appointment.resourceBookings;
1974
+ if (!resourceBookings || resourceBookings.length === 0) {
1975
+ Logger.debug(
1976
+ `[ResourceCalendarAdminService] No resource bookings on appointment ${appointment.id}, skipping time update.`
1977
+ );
1978
+ return;
1979
+ }
1980
+ Logger.info(
1981
+ `[ResourceCalendarAdminService] Updating ${resourceBookings.length} resource calendar event time(s) for appointment ${appointment.id}`
1982
+ );
1983
+ const batch = this.db.batch();
1984
+ const serverTimestamp = admin5.firestore.FieldValue.serverTimestamp();
1985
+ for (const booking of resourceBookings) {
1986
+ const eventPath = this.getResourceCalendarEventPath(
1987
+ appointment.clinicBranchId,
1988
+ booking
1989
+ );
1990
+ const eventRef = this.db.doc(eventPath);
1991
+ batch.update(eventRef, {
1992
+ eventTime: {
1993
+ start: newEventTime.start,
1994
+ end: newEventTime.end
1995
+ },
1996
+ updatedAt: serverTimestamp
1997
+ });
1998
+ Logger.debug(
1999
+ `[ResourceCalendarAdminService] Added time update for resource event ${booking.calendarEventId} (${booking.resourceName} / ${booking.resourceInstanceLabel})`
2000
+ );
2001
+ }
2002
+ try {
2003
+ await batch.commit();
2004
+ Logger.info(
2005
+ `[ResourceCalendarAdminService] Successfully updated ${resourceBookings.length} resource calendar event times for appointment ${appointment.id}.`
2006
+ );
2007
+ } catch (error) {
2008
+ Logger.error(
2009
+ `[ResourceCalendarAdminService] Error updating resource calendar event times for appointment ${appointment.id}:`,
2010
+ error
2011
+ );
2012
+ throw error;
2013
+ }
2014
+ }
2015
+ /**
2016
+ * Deletes all resource calendar events associated with a given appointment.
2017
+ *
2018
+ * @param appointment - The appointment object containing resourceBookings.
2019
+ */
2020
+ async deleteResourceBookingEvents(appointment) {
2021
+ const resourceBookings = appointment.resourceBookings;
2022
+ if (!resourceBookings || resourceBookings.length === 0) {
2023
+ Logger.debug(
2024
+ `[ResourceCalendarAdminService] No resource bookings on appointment ${appointment.id}, skipping deletion.`
2025
+ );
2026
+ return;
2027
+ }
2028
+ Logger.info(
2029
+ `[ResourceCalendarAdminService] Deleting ${resourceBookings.length} resource calendar event(s) for appointment ${appointment.id}`
2030
+ );
2031
+ const batch = this.db.batch();
2032
+ for (const booking of resourceBookings) {
2033
+ const eventPath = this.getResourceCalendarEventPath(
2034
+ appointment.clinicBranchId,
2035
+ booking
2036
+ );
2037
+ const eventRef = this.db.doc(eventPath);
2038
+ batch.delete(eventRef);
2039
+ Logger.debug(
2040
+ `[ResourceCalendarAdminService] Added deletion for resource event ${booking.calendarEventId} (${booking.resourceName} / ${booking.resourceInstanceLabel})`
2041
+ );
2042
+ }
2043
+ try {
2044
+ await batch.commit();
2045
+ Logger.info(
2046
+ `[ResourceCalendarAdminService] Successfully deleted ${resourceBookings.length} resource calendar events for appointment ${appointment.id}.`
2047
+ );
2048
+ } catch (error) {
2049
+ Logger.error(
2050
+ `[ResourceCalendarAdminService] Error deleting resource calendar events for appointment ${appointment.id}:`,
2051
+ error
2052
+ );
2053
+ throw error;
2054
+ }
2055
+ }
2056
+ };
2057
+
1899
2058
  // src/admin/mailing/appointment/appointment.mailing.service.ts
1900
2059
  var import_luxon = require("luxon");
1901
2060
 
1902
2061
  // src/admin/mailing/base.mailing.service.ts
1903
- var admin5 = __toESM(require("firebase-admin"));
2062
+ var admin6 = __toESM(require("firebase-admin"));
1904
2063
  var BaseMailingService = class {
1905
2064
  // Expecting the new mailgun.js client
1906
2065
  /**
@@ -1908,9 +2067,9 @@ var BaseMailingService = class {
1908
2067
  * @param firestore Firestore instance provided by the caller
1909
2068
  * @param mailgunClient Mailgun client instance (mailgun.js v10+) provided by the caller
1910
2069
  */
1911
- constructor(firestore19, mailgunClient) {
2070
+ constructor(firestore20, mailgunClient) {
1912
2071
  var _a;
1913
- this.db = firestore19;
2072
+ this.db = firestore20;
1914
2073
  this.mailgunClient = mailgunClient;
1915
2074
  if (!this.db) {
1916
2075
  Logger.error("[BaseMailingService] No Firestore instance provided");
@@ -2010,7 +2169,7 @@ var BaseMailingService = class {
2010
2169
  status: error.status,
2011
2170
  stack: error.stack
2012
2171
  } : null,
2013
- sentAt: admin5.firestore.FieldValue.serverTimestamp()
2172
+ sentAt: admin6.firestore.FieldValue.serverTimestamp()
2014
2173
  });
2015
2174
  Logger.info(
2016
2175
  `[BaseMailingService] Email log recorded. Success: ${success}`
@@ -2717,8 +2876,8 @@ var appointmentRescheduledProposalTemplate = `
2717
2876
  </html>
2718
2877
  `;
2719
2878
  var AppointmentMailingService = class extends BaseMailingService {
2720
- constructor(firestore19, mailgunClient) {
2721
- super(firestore19, mailgunClient);
2879
+ constructor(firestore20, mailgunClient) {
2880
+ super(firestore20, mailgunClient);
2722
2881
  this.DEFAULT_MAILGUN_DOMAIN = "mg.metaesthetics.net";
2723
2882
  Logger.info("[AppointmentMailingService] Initialized.");
2724
2883
  }
@@ -3158,8 +3317,8 @@ var AppointmentAggregationService = class {
3158
3317
  * @param mailgunClient - An initialized Mailgun client instance.
3159
3318
  * @param firestore Optional Firestore instance. If not provided, it uses the default admin SDK instance.
3160
3319
  */
3161
- constructor(mailgunClient, firestore19) {
3162
- this.db = firestore19 || admin6.firestore();
3320
+ constructor(mailgunClient, firestore20) {
3321
+ this.db = firestore20 || admin7.firestore();
3163
3322
  this.appointmentMailingService = new AppointmentMailingService(
3164
3323
  this.db,
3165
3324
  mailgunClient
@@ -3167,6 +3326,7 @@ var AppointmentAggregationService = class {
3167
3326
  );
3168
3327
  this.notificationsAdmin = new NotificationsAdmin(this.db);
3169
3328
  this.calendarAdminService = new CalendarAdminService(this.db);
3329
+ this.resourceCalendarAdminService = new ResourceCalendarAdminService(this.db);
3170
3330
  this.patientRequirementsAdminService = new PatientRequirementsAdminService(this.db);
3171
3331
  Logger.info("[AppointmentAggregationService] Initialized.");
3172
3332
  }
@@ -3308,6 +3468,10 @@ var AppointmentAggregationService = class {
3308
3468
  after,
3309
3469
  "confirmed" /* CONFIRMED */
3310
3470
  );
3471
+ await this.resourceCalendarAdminService.updateResourceBookingEventsStatus(
3472
+ after,
3473
+ "confirmed" /* CONFIRMED */
3474
+ );
3311
3475
  if ((patientSensitiveInfo == null ? void 0 : patientSensitiveInfo.email) && patientProfile) {
3312
3476
  Logger.info(
3313
3477
  `[AggService] Sending appointment confirmed email to patient ${patientSensitiveInfo.email}`
@@ -3358,6 +3522,10 @@ var AppointmentAggregationService = class {
3358
3522
  after,
3359
3523
  "confirmed" /* CONFIRMED */
3360
3524
  );
3525
+ await this.resourceCalendarAdminService.updateResourceBookingEventsStatus(
3526
+ after,
3527
+ "confirmed" /* CONFIRMED */
3528
+ );
3361
3529
  if ((patientSensitiveInfo == null ? void 0 : patientSensitiveInfo.email) && patientProfile) {
3362
3530
  Logger.info(
3363
3531
  `[AggService] Sending appointment confirmed email to patient ${patientSensitiveInfo.email}`
@@ -3425,6 +3593,10 @@ var AppointmentAggregationService = class {
3425
3593
  after,
3426
3594
  calendarStatus(after.status)
3427
3595
  );
3596
+ await this.resourceCalendarAdminService.updateResourceBookingEventsStatus(
3597
+ after,
3598
+ calendarStatus(after.status)
3599
+ );
3428
3600
  if ((patientSensitiveInfo == null ? void 0 : patientSensitiveInfo.email) && patientProfile) {
3429
3601
  Logger.info(
3430
3602
  `[AggService] Sending appointment cancellation email to patient ${patientSensitiveInfo.email}`
@@ -3471,6 +3643,10 @@ var AppointmentAggregationService = class {
3471
3643
  after,
3472
3644
  "completed" /* COMPLETED */
3473
3645
  );
3646
+ await this.resourceCalendarAdminService.updateResourceBookingEventsStatus(
3647
+ after,
3648
+ "completed" /* COMPLETED */
3649
+ );
3474
3650
  if ((patientSensitiveInfo == null ? void 0 : patientSensitiveInfo.email) && patientProfile) {
3475
3651
  Logger.info(
3476
3652
  `[AggService] Sending review request email to patient ${patientSensitiveInfo.email}`
@@ -3501,6 +3677,14 @@ var AppointmentAggregationService = class {
3501
3677
  after,
3502
3678
  "pending" /* PENDING */
3503
3679
  );
3680
+ await this.resourceCalendarAdminService.updateResourceBookingEventsTime(after, {
3681
+ start: after.appointmentStartTime,
3682
+ end: after.appointmentEndTime
3683
+ });
3684
+ await this.resourceCalendarAdminService.updateResourceBookingEventsStatus(
3685
+ after,
3686
+ "pending" /* PENDING */
3687
+ );
3504
3688
  if ((patientSensitiveInfo == null ? void 0 : patientSensitiveInfo.email) && patientProfile) {
3505
3689
  Logger.info(
3506
3690
  `[AggService] Sending reschedule proposal email to patient ${patientSensitiveInfo.email}`
@@ -3544,6 +3728,10 @@ var AppointmentAggregationService = class {
3544
3728
  start: after.appointmentStartTime,
3545
3729
  end: after.appointmentEndTime
3546
3730
  });
3731
+ await this.resourceCalendarAdminService.updateResourceBookingEventsTime(after, {
3732
+ start: after.appointmentStartTime,
3733
+ end: after.appointmentEndTime
3734
+ });
3547
3735
  } else {
3548
3736
  Logger.warn(
3549
3737
  `[AggService] Independent time change detected for ${after.id} with status ${after.status}. Review implications for requirements and calendar.`
@@ -3588,6 +3776,7 @@ var AppointmentAggregationService = class {
3588
3776
  );
3589
3777
  }
3590
3778
  await this.calendarAdminService.deleteAppointmentCalendarEvents(deletedAppointment);
3779
+ await this.resourceCalendarAdminService.deleteResourceBookingEvents(deletedAppointment);
3591
3780
  }
3592
3781
  // --- Helper Methods for Aggregation Logic ---
3593
3782
  /**
@@ -3679,7 +3868,7 @@ var AppointmentAggregationService = class {
3679
3868
  } else if (template.timeframe.unit === "hours" /* HOURS */) {
3680
3869
  dueDateTime.setHours(dueDateTime.getHours() - notifyAtValue);
3681
3870
  }
3682
- dueTime = admin6.firestore.Timestamp.fromDate(dueDateTime);
3871
+ dueTime = admin7.firestore.Timestamp.fromDate(dueDateTime);
3683
3872
  }
3684
3873
  const actionableWindowHours = template.importance === "high" ? 1 : template.importance === "medium" ? 4 : 15;
3685
3874
  const instructionObject = {
@@ -3694,7 +3883,7 @@ var AppointmentAggregationService = class {
3694
3883
  status: "pendingNotification" /* PENDING_NOTIFICATION */,
3695
3884
  originalNotifyAtValue: notifyAtValue,
3696
3885
  originalTimeframeUnit: template.timeframe.unit,
3697
- updatedAt: admin6.firestore.Timestamp.now()
3886
+ updatedAt: admin7.firestore.Timestamp.now()
3698
3887
  // Use current server timestamp
3699
3888
  };
3700
3889
  return instructionObject;
@@ -3713,8 +3902,8 @@ var AppointmentAggregationService = class {
3713
3902
  overallStatus: "active" /* ACTIVE */,
3714
3903
  instructions,
3715
3904
  // Timestamps - cast to any to satisfy client-side Timestamp type for now
3716
- createdAt: admin6.firestore.FieldValue.serverTimestamp(),
3717
- updatedAt: admin6.firestore.FieldValue.serverTimestamp()
3905
+ createdAt: admin7.firestore.FieldValue.serverTimestamp(),
3906
+ updatedAt: admin7.firestore.FieldValue.serverTimestamp()
3718
3907
  };
3719
3908
  Logger.debug(
3720
3909
  `[AggService] Setting data for requirement: ${JSON.stringify({
@@ -4064,7 +4253,7 @@ var AppointmentAggregationService = class {
4064
4253
  } else if (template.timeframe.unit === "hours" /* HOURS */) {
4065
4254
  dueDateTime.setHours(dueDateTime.getHours() + notifyAtValue);
4066
4255
  }
4067
- dueTime = admin6.firestore.Timestamp.fromDate(dueDateTime);
4256
+ dueTime = admin7.firestore.Timestamp.fromDate(dueDateTime);
4068
4257
  }
4069
4258
  const actionableWindowHours = template.importance === "high" ? 1 : template.importance === "medium" ? 4 : 15;
4070
4259
  const instructionObject = {
@@ -4078,7 +4267,7 @@ var AppointmentAggregationService = class {
4078
4267
  status: "pendingNotification" /* PENDING_NOTIFICATION */,
4079
4268
  originalNotifyAtValue: notifyAtValue,
4080
4269
  originalTimeframeUnit: template.timeframe.unit,
4081
- updatedAt: admin6.firestore.Timestamp.now(),
4270
+ updatedAt: admin7.firestore.Timestamp.now(),
4082
4271
  notificationId: void 0,
4083
4272
  actionTakenAt: void 0
4084
4273
  };
@@ -4097,8 +4286,8 @@ var AppointmentAggregationService = class {
4097
4286
  instructions,
4098
4287
  sourceProcedures: reqWithSource.sourceProcedures,
4099
4288
  // Track which procedures this requirement comes from
4100
- createdAt: admin6.firestore.FieldValue.serverTimestamp(),
4101
- updatedAt: admin6.firestore.FieldValue.serverTimestamp()
4289
+ createdAt: admin7.firestore.FieldValue.serverTimestamp(),
4290
+ updatedAt: admin7.firestore.FieldValue.serverTimestamp()
4102
4291
  };
4103
4292
  Logger.debug(
4104
4293
  `[AggService] Setting data for requirement: ${JSON.stringify({
@@ -4258,7 +4447,7 @@ var AppointmentAggregationService = class {
4258
4447
  if (instance.overallStatus !== newOverallStatus && instance.overallStatus !== "failedToProcess" /* FAILED_TO_PROCESS */) {
4259
4448
  batch.update(doc3.ref, {
4260
4449
  overallStatus: newOverallStatus,
4261
- updatedAt: admin6.firestore.FieldValue.serverTimestamp()
4450
+ updatedAt: admin7.firestore.FieldValue.serverTimestamp()
4262
4451
  // Cast for now
4263
4452
  // Potentially also cancel individual instructions if not handled by another trigger
4264
4453
  // instructions: instance.instructions.map(instr => ({ ...instr, status: PatientInstructionStatus.CANCELLED, updatedAt: admin.firestore.FieldValue.serverTimestamp() as any }))
@@ -4334,17 +4523,17 @@ var AppointmentAggregationService = class {
4334
4523
  if (!hasDoctor || !hasClinic) {
4335
4524
  const patientRef = this.db.collection(PATIENTS_COLLECTION).doc(patientProfile.id);
4336
4525
  const updateData = {
4337
- updatedAt: admin6.firestore.FieldValue.serverTimestamp()
4526
+ updatedAt: admin7.firestore.FieldValue.serverTimestamp()
4338
4527
  };
4339
4528
  if (!hasDoctor) {
4340
4529
  Logger.debug(
4341
4530
  `[AggService] Adding practitioner ${practitionerId} to patient ${patientProfile.id}`
4342
4531
  );
4343
- updateData.doctorIds = admin6.firestore.FieldValue.arrayUnion(practitionerId);
4532
+ updateData.doctorIds = admin7.firestore.FieldValue.arrayUnion(practitionerId);
4344
4533
  }
4345
4534
  if (!hasClinic) {
4346
4535
  Logger.debug(`[AggService] Adding clinic ${clinicId} to patient ${patientProfile.id}`);
4347
- updateData.clinicIds = admin6.firestore.FieldValue.arrayUnion(clinicId);
4536
+ updateData.clinicIds = admin7.firestore.FieldValue.arrayUnion(clinicId);
4348
4537
  }
4349
4538
  await patientRef.update(updateData);
4350
4539
  Logger.info(
@@ -4394,16 +4583,16 @@ var AppointmentAggregationService = class {
4394
4583
  Logger.debug(
4395
4584
  `[AggService] Removing practitioner ${practitionerId} from patient ${patientProfile.id}`
4396
4585
  );
4397
- updateData.doctorIds = admin6.firestore.FieldValue.arrayRemove(practitionerId);
4586
+ updateData.doctorIds = admin7.firestore.FieldValue.arrayRemove(practitionerId);
4398
4587
  updateNeeded = true;
4399
4588
  }
4400
4589
  if (activeClinicAppointments === 0 && ((_b = patientProfile.clinicIds) == null ? void 0 : _b.includes(clinicId))) {
4401
4590
  Logger.debug(`[AggService] Removing clinic ${clinicId} from patient ${patientProfile.id}`);
4402
- updateData.clinicIds = admin6.firestore.FieldValue.arrayRemove(clinicId);
4591
+ updateData.clinicIds = admin7.firestore.FieldValue.arrayRemove(clinicId);
4403
4592
  updateNeeded = true;
4404
4593
  }
4405
4594
  if (updateNeeded) {
4406
- updateData.updatedAt = admin6.firestore.FieldValue.serverTimestamp();
4595
+ updateData.updatedAt = admin7.firestore.FieldValue.serverTimestamp();
4407
4596
  await patientRef.update(updateData);
4408
4597
  Logger.info(`[AggService] Successfully removed links from patient ${patientProfile.id}`);
4409
4598
  } else {
@@ -4694,7 +4883,7 @@ var AppointmentAggregationService = class {
4694
4883
  userId: after.patientId,
4695
4884
  userRole: "patient" /* PATIENT */,
4696
4885
  notificationType: "procedureRecommendation" /* PROCEDURE_RECOMMENDATION */,
4697
- notificationTime: admin6.firestore.Timestamp.now(),
4886
+ notificationTime: admin7.firestore.Timestamp.now(),
4698
4887
  notificationTokens: (patientProfile == null ? void 0 : patientProfile.expoTokens) || [],
4699
4888
  title: "New Procedure Recommendation",
4700
4889
  body: `${((_c = after.practitionerInfo) == null ? void 0 : _c.name) || "Your doctor"} recommended "${recommendation.procedure.procedureName}" for you. Suggested timeframe: in ${timeframeText}`,
@@ -4740,15 +4929,15 @@ var AppointmentAggregationService = class {
4740
4929
  };
4741
4930
 
4742
4931
  // src/admin/aggregation/clinic/clinic.aggregation.service.ts
4743
- var admin7 = __toESM(require("firebase-admin"));
4932
+ var admin8 = __toESM(require("firebase-admin"));
4744
4933
  var CALENDAR_SUBCOLLECTION_ID = "calendar";
4745
4934
  var ClinicAggregationService = class {
4746
4935
  /**
4747
4936
  * Constructor for ClinicAggregationService.
4748
4937
  * @param firestore Optional Firestore instance. If not provided, it uses the default admin SDK instance.
4749
4938
  */
4750
- constructor(firestore19) {
4751
- this.db = firestore19 || admin7.firestore();
4939
+ constructor(firestore20) {
4940
+ this.db = firestore20 || admin8.firestore();
4752
4941
  }
4753
4942
  /**
4754
4943
  * Adds clinic information to a clinic group when a new clinic is created
@@ -4771,9 +4960,9 @@ var ClinicAggregationService = class {
4771
4960
  );
4772
4961
  try {
4773
4962
  await groupRef.update({
4774
- clinicsInfo: admin7.firestore.FieldValue.arrayUnion(clinicInfo),
4775
- clinicIds: admin7.firestore.FieldValue.arrayUnion(clinicId),
4776
- updatedAt: admin7.firestore.FieldValue.serverTimestamp()
4963
+ clinicsInfo: admin8.firestore.FieldValue.arrayUnion(clinicInfo),
4964
+ clinicIds: admin8.firestore.FieldValue.arrayUnion(clinicId),
4965
+ updatedAt: admin8.firestore.FieldValue.serverTimestamp()
4777
4966
  });
4778
4967
  console.log(
4779
4968
  `[ClinicAggregationService] Successfully added ClinicInfo (ID: ${clinicId}) to Clinic Group ${clinicGroupId}.`
@@ -4818,7 +5007,7 @@ var ClinicAggregationService = class {
4818
5007
  const updatedClinicsInfo = [...filteredClinicsInfo, clinicInfo];
4819
5008
  batch.update(practitionerRef, {
4820
5009
  clinicsInfo: updatedClinicsInfo,
4821
- updatedAt: admin7.firestore.FieldValue.serverTimestamp()
5010
+ updatedAt: admin8.firestore.FieldValue.serverTimestamp()
4822
5011
  });
4823
5012
  }
4824
5013
  }
@@ -4856,7 +5045,7 @@ var ClinicAggregationService = class {
4856
5045
  const procedureRef = this.db.collection(PROCEDURES_COLLECTION).doc(procedureId);
4857
5046
  batch.update(procedureRef, {
4858
5047
  clinicInfo,
4859
- updatedAt: admin7.firestore.FieldValue.serverTimestamp()
5048
+ updatedAt: admin8.firestore.FieldValue.serverTimestamp()
4860
5049
  });
4861
5050
  }
4862
5051
  try {
@@ -4900,7 +5089,7 @@ var ClinicAggregationService = class {
4900
5089
  const updatedClinicsInfo = [...filteredClinicsInfo, clinicInfo];
4901
5090
  await groupRef.update({
4902
5091
  clinicsInfo: updatedClinicsInfo,
4903
- updatedAt: admin7.firestore.FieldValue.serverTimestamp()
5092
+ updatedAt: admin8.firestore.FieldValue.serverTimestamp()
4904
5093
  });
4905
5094
  console.log(
4906
5095
  `[ClinicAggregationService] Successfully updated ClinicInfo (ID: ${clinicId}) in Clinic Group ${clinicGroupId}.`
@@ -4959,7 +5148,7 @@ var ClinicAggregationService = class {
4959
5148
  console.log(
4960
5149
  `[ClinicAggregationService] Querying upcoming calendar events via collection group '${CALENDAR_SUBCOLLECTION_ID}' for clinic ${clinicId} to update location.`
4961
5150
  );
4962
- const now = admin7.firestore.Timestamp.now();
5151
+ const now = admin8.firestore.Timestamp.now();
4963
5152
  const calendarEventsQuery = this.db.collectionGroup(CALENDAR_SUBCOLLECTION_ID).where("clinicBranchId", "==", clinicId).where("eventTime.start", ">", now);
4964
5153
  try {
4965
5154
  const snapshot = await calendarEventsQuery.get();
@@ -4976,7 +5165,7 @@ var ClinicAggregationService = class {
4976
5165
  );
4977
5166
  batch.update(doc3.ref, {
4978
5167
  eventLocation: newLocation,
4979
- updatedAt: admin7.firestore.FieldValue.serverTimestamp()
5168
+ updatedAt: admin8.firestore.FieldValue.serverTimestamp()
4980
5169
  });
4981
5170
  });
4982
5171
  await batch.commit();
@@ -5006,7 +5195,7 @@ var ClinicAggregationService = class {
5006
5195
  console.log(
5007
5196
  `[ClinicAggregationService] Querying upcoming calendar events for clinic ${clinicId} to update clinic info.`
5008
5197
  );
5009
- const now = admin7.firestore.Timestamp.now();
5198
+ const now = admin8.firestore.Timestamp.now();
5010
5199
  const calendarEventsQuery = this.db.collectionGroup(CALENDAR_SUBCOLLECTION_ID).where("clinicBranchId", "==", clinicId).where("eventTime.start", ">", now);
5011
5200
  try {
5012
5201
  const snapshot = await calendarEventsQuery.get();
@@ -5023,7 +5212,7 @@ var ClinicAggregationService = class {
5023
5212
  );
5024
5213
  batch.update(doc3.ref, {
5025
5214
  clinicInfo,
5026
- updatedAt: admin7.firestore.FieldValue.serverTimestamp()
5215
+ updatedAt: admin8.firestore.FieldValue.serverTimestamp()
5027
5216
  });
5028
5217
  });
5029
5218
  await batch.commit();
@@ -5072,7 +5261,7 @@ var ClinicAggregationService = class {
5072
5261
  batch.update(practitionerRef, {
5073
5262
  clinics: filteredClinicIds,
5074
5263
  clinicsInfo: filteredClinicsInfo,
5075
- updatedAt: admin7.firestore.FieldValue.serverTimestamp()
5264
+ updatedAt: admin8.firestore.FieldValue.serverTimestamp()
5076
5265
  });
5077
5266
  if (checkAndDeactivateDoctors) {
5078
5267
  practitionersToCheck.push(practitionerId);
@@ -5124,7 +5313,7 @@ var ClinicAggregationService = class {
5124
5313
  );
5125
5314
  batch.update(practitionerRef, {
5126
5315
  isActive: false,
5127
- updatedAt: admin7.firestore.FieldValue.serverTimestamp()
5316
+ updatedAt: admin8.firestore.FieldValue.serverTimestamp()
5128
5317
  });
5129
5318
  deactivationCount++;
5130
5319
  } else {
@@ -5146,7 +5335,7 @@ var ClinicAggregationService = class {
5146
5335
  );
5147
5336
  batch.update(practitionerRef, {
5148
5337
  isActive: false,
5149
- updatedAt: admin7.firestore.FieldValue.serverTimestamp()
5338
+ updatedAt: admin8.firestore.FieldValue.serverTimestamp()
5150
5339
  });
5151
5340
  deactivationCount++;
5152
5341
  }
@@ -5203,7 +5392,7 @@ var ClinicAggregationService = class {
5203
5392
  );
5204
5393
  batch.update(practitionerRef, {
5205
5394
  isActive: true,
5206
- updatedAt: admin7.firestore.FieldValue.serverTimestamp()
5395
+ updatedAt: admin8.firestore.FieldValue.serverTimestamp()
5207
5396
  });
5208
5397
  reactivationCount++;
5209
5398
  } else {
@@ -5225,7 +5414,7 @@ var ClinicAggregationService = class {
5225
5414
  );
5226
5415
  batch.update(practitionerRef, {
5227
5416
  isActive: true,
5228
- updatedAt: admin7.firestore.FieldValue.serverTimestamp()
5417
+ updatedAt: admin8.firestore.FieldValue.serverTimestamp()
5229
5418
  });
5230
5419
  reactivationCount++;
5231
5420
  }
@@ -5271,7 +5460,7 @@ var ClinicAggregationService = class {
5271
5460
  const procedureRef = this.db.collection(PROCEDURES_COLLECTION).doc(procedureId);
5272
5461
  batch.update(procedureRef, {
5273
5462
  isActive: false,
5274
- updatedAt: admin7.firestore.FieldValue.serverTimestamp()
5463
+ updatedAt: admin8.firestore.FieldValue.serverTimestamp()
5275
5464
  });
5276
5465
  }
5277
5466
  try {
@@ -5310,7 +5499,7 @@ var ClinicAggregationService = class {
5310
5499
  if (procedureDoc.exists) {
5311
5500
  batch.update(procedureRef, {
5312
5501
  isActive: true,
5313
- updatedAt: admin7.firestore.FieldValue.serverTimestamp()
5502
+ updatedAt: admin8.firestore.FieldValue.serverTimestamp()
5314
5503
  });
5315
5504
  reactivationCount++;
5316
5505
  } else {
@@ -5369,7 +5558,7 @@ var ClinicAggregationService = class {
5369
5558
  await groupRef.update({
5370
5559
  clinics: filteredClinicIds,
5371
5560
  clinicsInfo: filteredClinicsInfo,
5372
- updatedAt: admin7.firestore.FieldValue.serverTimestamp()
5561
+ updatedAt: admin8.firestore.FieldValue.serverTimestamp()
5373
5562
  });
5374
5563
  console.log(
5375
5564
  `[ClinicAggregationService] Successfully removed Clinic (ID: ${clinicId}) from Clinic Group ${clinicGroupId}.`
@@ -5406,8 +5595,8 @@ var ClinicAggregationService = class {
5406
5595
  for (const patientId of patientIds) {
5407
5596
  const patientRef = this.db.collection(PATIENTS_COLLECTION).doc(patientId);
5408
5597
  batch.update(patientRef, {
5409
- clinicIds: admin7.firestore.FieldValue.arrayRemove(clinicId),
5410
- updatedAt: admin7.firestore.FieldValue.serverTimestamp()
5598
+ clinicIds: admin8.firestore.FieldValue.arrayRemove(clinicId),
5599
+ updatedAt: admin8.firestore.FieldValue.serverTimestamp()
5411
5600
  });
5412
5601
  }
5413
5602
  try {
@@ -5437,7 +5626,7 @@ var ClinicAggregationService = class {
5437
5626
  console.log(
5438
5627
  `[ClinicAggregationService] Querying upcoming calendar events for clinic ${clinicId} to cancel.`
5439
5628
  );
5440
- const now = admin7.firestore.Timestamp.now();
5629
+ const now = admin8.firestore.Timestamp.now();
5441
5630
  const calendarEventsQuery = this.db.collectionGroup(CALENDAR_SUBCOLLECTION_ID).where("clinicBranchId", "==", clinicId).where("eventTime.start", ">", now);
5442
5631
  try {
5443
5632
  const snapshot = await calendarEventsQuery.get();
@@ -5455,7 +5644,7 @@ var ClinicAggregationService = class {
5455
5644
  batch.update(doc3.ref, {
5456
5645
  status: "CANCELED",
5457
5646
  cancelReason: "Clinic deleted",
5458
- updatedAt: admin7.firestore.FieldValue.serverTimestamp()
5647
+ updatedAt: admin8.firestore.FieldValue.serverTimestamp()
5459
5648
  });
5460
5649
  });
5461
5650
  await batch.commit();
@@ -5473,14 +5662,14 @@ var ClinicAggregationService = class {
5473
5662
  };
5474
5663
 
5475
5664
  // src/admin/aggregation/forms/filled-forms.aggregation.service.ts
5476
- var admin8 = __toESM(require("firebase-admin"));
5665
+ var admin9 = __toESM(require("firebase-admin"));
5477
5666
  var FilledFormsAggregationService = class {
5478
5667
  /**
5479
5668
  * Constructor for FilledFormsAggregationService.
5480
5669
  * @param firestore Optional Firestore instance. If not provided, it uses the default admin SDK instance.
5481
5670
  */
5482
- constructor(firestore19) {
5483
- this.db = firestore19 || admin8.firestore();
5671
+ constructor(firestore20) {
5672
+ this.db = firestore20 || admin9.firestore();
5484
5673
  Logger.info("[FilledFormsAggregationService] Initialized");
5485
5674
  }
5486
5675
  /**
@@ -5539,12 +5728,12 @@ var FilledFormsAggregationService = class {
5539
5728
  path: `${APPOINTMENTS_COLLECTION}/${filledDocument.appointmentId}/${formSubcollection}/${filledDocument.id}`
5540
5729
  };
5541
5730
  if (filledDocument.updatedAt) {
5542
- linkedFormInfo.submittedAt = admin8.firestore.Timestamp.fromMillis(
5731
+ linkedFormInfo.submittedAt = admin9.firestore.Timestamp.fromMillis(
5543
5732
  filledDocument.updatedAt
5544
5733
  );
5545
5734
  }
5546
5735
  if (filledDocument.status === "completed" /* COMPLETED */ || filledDocument.status === "signed" /* SIGNED */) {
5547
- linkedFormInfo.completedAt = admin8.firestore.Timestamp.fromMillis(
5736
+ linkedFormInfo.completedAt = admin9.firestore.Timestamp.fromMillis(
5548
5737
  filledDocument.updatedAt
5549
5738
  );
5550
5739
  }
@@ -5558,7 +5747,7 @@ var FilledFormsAggregationService = class {
5558
5747
  updatedLinkedForms.push(linkedFormInfo);
5559
5748
  updateData = {
5560
5749
  linkedForms: updatedLinkedForms,
5561
- updatedAt: admin8.firestore.FieldValue.serverTimestamp()
5750
+ updatedAt: admin9.firestore.FieldValue.serverTimestamp()
5562
5751
  };
5563
5752
  let updatedLinkedFormIds = appointment.linkedFormIds || [];
5564
5753
  if (!updatedLinkedFormIds.includes(filledDocument.id)) {
@@ -5567,7 +5756,7 @@ var FilledFormsAggregationService = class {
5567
5756
  }
5568
5757
  if (filledDocument.isUserForm && filledDocument.isRequired && (filledDocument.status === "completed" /* COMPLETED */ || filledDocument.status === "signed" /* SIGNED */)) {
5569
5758
  if (appointment.pendingUserFormsIds && appointment.pendingUserFormsIds.includes(filledDocument.id)) {
5570
- updateData.pendingUserFormsIds = admin8.firestore.FieldValue.arrayRemove(
5759
+ updateData.pendingUserFormsIds = admin9.firestore.FieldValue.arrayRemove(
5571
5760
  filledDocument.id
5572
5761
  );
5573
5762
  Logger.info(
@@ -5613,21 +5802,21 @@ var FilledFormsAggregationService = class {
5613
5802
  (form) => form.formId === filledDocument.id
5614
5803
  );
5615
5804
  if (formToRemove) {
5616
- updateData.linkedForms = admin8.firestore.FieldValue.arrayRemove(formToRemove);
5805
+ updateData.linkedForms = admin9.firestore.FieldValue.arrayRemove(formToRemove);
5617
5806
  }
5618
5807
  }
5619
5808
  if (appointment.linkedFormIds && appointment.linkedFormIds.includes(filledDocument.id)) {
5620
- updateData.linkedFormIds = admin8.firestore.FieldValue.arrayRemove(filledDocument.id);
5809
+ updateData.linkedFormIds = admin9.firestore.FieldValue.arrayRemove(filledDocument.id);
5621
5810
  }
5622
5811
  if (filledDocument.isUserForm && filledDocument.isRequired) {
5623
5812
  if (filledDocument.status !== "completed" /* COMPLETED */ && filledDocument.status !== "signed" /* SIGNED */) {
5624
5813
  if (!appointment.pendingUserFormsIds || !appointment.pendingUserFormsIds.includes(filledDocument.id)) {
5625
- updateData.pendingUserFormsIds = appointment.pendingUserFormsIds ? admin8.firestore.FieldValue.arrayUnion(filledDocument.id) : [filledDocument.id];
5814
+ updateData.pendingUserFormsIds = appointment.pendingUserFormsIds ? admin9.firestore.FieldValue.arrayUnion(filledDocument.id) : [filledDocument.id];
5626
5815
  }
5627
5816
  }
5628
5817
  }
5629
5818
  if (Object.keys(updateData).length > 0) {
5630
- updateData.updatedAt = admin8.firestore.FieldValue.serverTimestamp();
5819
+ updateData.updatedAt = admin9.firestore.FieldValue.serverTimestamp();
5631
5820
  await appointmentRef.update(updateData);
5632
5821
  Logger.info(
5633
5822
  `[FilledFormsAggregationService] Successfully updated appointment ${filledDocument.appointmentId} after form deletion`
@@ -5667,8 +5856,8 @@ var FilledFormsAggregationService = class {
5667
5856
  return;
5668
5857
  }
5669
5858
  await appointmentRef.update({
5670
- pendingUserFormsIds: admin8.firestore.FieldValue.arrayUnion(filledDocument.id),
5671
- updatedAt: admin8.firestore.FieldValue.serverTimestamp()
5859
+ pendingUserFormsIds: admin9.firestore.FieldValue.arrayUnion(filledDocument.id),
5860
+ updatedAt: admin9.firestore.FieldValue.serverTimestamp()
5672
5861
  });
5673
5862
  Logger.info(
5674
5863
  `[FilledFormsAggregationService] Successfully added form ${filledDocument.id} to pendingUserFormsIds for appointment ${filledDocument.appointmentId}`
@@ -5684,11 +5873,11 @@ var FilledFormsAggregationService = class {
5684
5873
  };
5685
5874
 
5686
5875
  // src/admin/aggregation/patient/patient.aggregation.service.ts
5687
- var admin9 = __toESM(require("firebase-admin"));
5876
+ var admin10 = __toESM(require("firebase-admin"));
5688
5877
  var CALENDAR_SUBCOLLECTION_ID2 = "calendar";
5689
5878
  var PatientAggregationService = class {
5690
- constructor(firestore19) {
5691
- this.db = firestore19 || admin9.firestore();
5879
+ constructor(firestore20) {
5880
+ this.db = firestore20 || admin10.firestore();
5692
5881
  }
5693
5882
  // --- Methods for Patient Creation --- >
5694
5883
  // No specific aggregations defined for patient creation in the plan.
@@ -5709,7 +5898,7 @@ var PatientAggregationService = class {
5709
5898
  console.log(
5710
5899
  `[PatientAggregationService] Querying upcoming calendar events for patient ${patientId} to update patient info.`
5711
5900
  );
5712
- const now = admin9.firestore.Timestamp.now();
5901
+ const now = admin10.firestore.Timestamp.now();
5713
5902
  const calendarEventsQuery = this.db.collectionGroup(CALENDAR_SUBCOLLECTION_ID2).where("patientId", "==", patientId).where("eventTime.start", ">", now);
5714
5903
  try {
5715
5904
  const snapshot = await calendarEventsQuery.get();
@@ -5726,7 +5915,7 @@ var PatientAggregationService = class {
5726
5915
  );
5727
5916
  batch.update(doc3.ref, {
5728
5917
  patientInfo,
5729
- updatedAt: admin9.firestore.FieldValue.serverTimestamp()
5918
+ updatedAt: admin10.firestore.FieldValue.serverTimestamp()
5730
5919
  });
5731
5920
  });
5732
5921
  await batch.commit();
@@ -5757,7 +5946,7 @@ var PatientAggregationService = class {
5757
5946
  console.log(
5758
5947
  `[PatientAggregationService] Querying upcoming calendar events for patient ${patientId} to cancel.`
5759
5948
  );
5760
- const now = admin9.firestore.Timestamp.now();
5949
+ const now = admin10.firestore.Timestamp.now();
5761
5950
  const calendarEventsQuery = this.db.collectionGroup(CALENDAR_SUBCOLLECTION_ID2).where("patientId", "==", patientId).where("eventTime.start", ">", now);
5762
5951
  try {
5763
5952
  const snapshot = await calendarEventsQuery.get();
@@ -5775,7 +5964,7 @@ var PatientAggregationService = class {
5775
5964
  batch.update(doc3.ref, {
5776
5965
  status: "CANCELED",
5777
5966
  cancelReason: "Patient deleted",
5778
- updatedAt: admin9.firestore.FieldValue.serverTimestamp()
5967
+ updatedAt: admin10.firestore.FieldValue.serverTimestamp()
5779
5968
  });
5780
5969
  });
5781
5970
  await batch.commit();
@@ -5793,11 +5982,11 @@ var PatientAggregationService = class {
5793
5982
  };
5794
5983
 
5795
5984
  // src/admin/aggregation/practitioner/practitioner.aggregation.service.ts
5796
- var admin10 = __toESM(require("firebase-admin"));
5985
+ var admin11 = __toESM(require("firebase-admin"));
5797
5986
  var CALENDAR_SUBCOLLECTION_ID3 = "calendar";
5798
5987
  var PractitionerAggregationService = class {
5799
- constructor(firestore19) {
5800
- this.db = firestore19 || admin10.firestore();
5988
+ constructor(firestore20) {
5989
+ this.db = firestore20 || admin11.firestore();
5801
5990
  }
5802
5991
  /**
5803
5992
  * Adds practitioner information to a clinic when a new practitioner is created
@@ -5819,9 +6008,9 @@ var PractitionerAggregationService = class {
5819
6008
  const clinicRef = this.db.collection(CLINICS_COLLECTION).doc(clinicId);
5820
6009
  try {
5821
6010
  await clinicRef.update({
5822
- doctors: admin10.firestore.FieldValue.arrayUnion(practitionerId),
5823
- doctorsInfo: admin10.firestore.FieldValue.arrayUnion(doctorInfo),
5824
- updatedAt: admin10.firestore.FieldValue.serverTimestamp()
6011
+ doctors: admin11.firestore.FieldValue.arrayUnion(practitionerId),
6012
+ doctorsInfo: admin11.firestore.FieldValue.arrayUnion(doctorInfo),
6013
+ updatedAt: admin11.firestore.FieldValue.serverTimestamp()
5825
6014
  });
5826
6015
  console.log(
5827
6016
  `[PractitionerAggregationService] Successfully added practitioner ${practitionerId} to clinic ${clinicId}.`
@@ -5855,14 +6044,14 @@ var PractitionerAggregationService = class {
5855
6044
  for (const clinicId of clinicIds) {
5856
6045
  const clinicRef = this.db.collection(CLINICS_COLLECTION).doc(clinicId);
5857
6046
  batch.update(clinicRef, {
5858
- doctorsInfo: admin10.firestore.FieldValue.arrayRemove({
6047
+ doctorsInfo: admin11.firestore.FieldValue.arrayRemove({
5859
6048
  id: practitionerId
5860
6049
  }),
5861
- updatedAt: admin10.firestore.FieldValue.serverTimestamp()
6050
+ updatedAt: admin11.firestore.FieldValue.serverTimestamp()
5862
6051
  });
5863
6052
  batch.update(clinicRef, {
5864
- doctorsInfo: admin10.firestore.FieldValue.arrayUnion(doctorInfo),
5865
- updatedAt: admin10.firestore.FieldValue.serverTimestamp()
6053
+ doctorsInfo: admin11.firestore.FieldValue.arrayUnion(doctorInfo),
6054
+ updatedAt: admin11.firestore.FieldValue.serverTimestamp()
5866
6055
  });
5867
6056
  }
5868
6057
  try {
@@ -5900,7 +6089,7 @@ var PractitionerAggregationService = class {
5900
6089
  const procedureRef = this.db.collection(PROCEDURES_COLLECTION).doc(procedureId);
5901
6090
  batch.update(procedureRef, {
5902
6091
  doctorInfo,
5903
- updatedAt: admin10.firestore.FieldValue.serverTimestamp()
6092
+ updatedAt: admin11.firestore.FieldValue.serverTimestamp()
5904
6093
  });
5905
6094
  }
5906
6095
  try {
@@ -5932,7 +6121,7 @@ var PractitionerAggregationService = class {
5932
6121
  console.log(
5933
6122
  `[PractitionerAggregationService] Querying upcoming calendar events for practitioner ${practitionerId} to update practitioner info.`
5934
6123
  );
5935
- const now = admin10.firestore.Timestamp.now();
6124
+ const now = admin11.firestore.Timestamp.now();
5936
6125
  const calendarEventsQuery = this.db.collectionGroup(CALENDAR_SUBCOLLECTION_ID3).where("practitionerId", "==", practitionerId).where("eventTime.start", ">", now);
5937
6126
  try {
5938
6127
  const snapshot = await calendarEventsQuery.get();
@@ -5949,7 +6138,7 @@ var PractitionerAggregationService = class {
5949
6138
  );
5950
6139
  batch.update(doc3.ref, {
5951
6140
  practitionerInfo,
5952
- updatedAt: admin10.firestore.FieldValue.serverTimestamp()
6141
+ updatedAt: admin11.firestore.FieldValue.serverTimestamp()
5953
6142
  });
5954
6143
  });
5955
6144
  await batch.commit();
@@ -5984,12 +6173,12 @@ var PractitionerAggregationService = class {
5984
6173
  for (const clinicId of clinicIds) {
5985
6174
  const clinicRef = this.db.collection(CLINICS_COLLECTION).doc(clinicId);
5986
6175
  batch.update(clinicRef, {
5987
- doctors: admin10.firestore.FieldValue.arrayRemove(practitionerId),
6176
+ doctors: admin11.firestore.FieldValue.arrayRemove(practitionerId),
5988
6177
  // Remove all doctor info objects where id matches the practitioner ID
5989
- doctorsInfo: admin10.firestore.FieldValue.arrayRemove({
6178
+ doctorsInfo: admin11.firestore.FieldValue.arrayRemove({
5990
6179
  id: practitionerId
5991
6180
  }),
5992
- updatedAt: admin10.firestore.FieldValue.serverTimestamp()
6181
+ updatedAt: admin11.firestore.FieldValue.serverTimestamp()
5993
6182
  });
5994
6183
  }
5995
6184
  try {
@@ -6020,7 +6209,7 @@ var PractitionerAggregationService = class {
6020
6209
  console.log(
6021
6210
  `[PractitionerAggregationService] Querying upcoming calendar events for practitioner ${practitionerId} to cancel.`
6022
6211
  );
6023
- const now = admin10.firestore.Timestamp.now();
6212
+ const now = admin11.firestore.Timestamp.now();
6024
6213
  const calendarEventsQuery = this.db.collectionGroup(CALENDAR_SUBCOLLECTION_ID3).where("practitionerId", "==", practitionerId).where("eventTime.start", ">", now);
6025
6214
  try {
6026
6215
  const snapshot = await calendarEventsQuery.get();
@@ -6038,7 +6227,7 @@ var PractitionerAggregationService = class {
6038
6227
  batch.update(doc3.ref, {
6039
6228
  status: "CANCELED",
6040
6229
  cancelReason: "Practitioner deleted",
6041
- updatedAt: admin10.firestore.FieldValue.serverTimestamp()
6230
+ updatedAt: admin11.firestore.FieldValue.serverTimestamp()
6042
6231
  });
6043
6232
  });
6044
6233
  await batch.commit();
@@ -6073,8 +6262,8 @@ var PractitionerAggregationService = class {
6073
6262
  for (const patientId of patientIds) {
6074
6263
  const patientRef = this.db.collection(PATIENTS_COLLECTION).doc(patientId);
6075
6264
  batch.update(patientRef, {
6076
- doctorIds: admin10.firestore.FieldValue.arrayRemove(practitionerId),
6077
- updatedAt: admin10.firestore.FieldValue.serverTimestamp()
6265
+ doctorIds: admin11.firestore.FieldValue.arrayRemove(practitionerId),
6266
+ updatedAt: admin11.firestore.FieldValue.serverTimestamp()
6078
6267
  });
6079
6268
  }
6080
6269
  try {
@@ -6110,7 +6299,7 @@ var PractitionerAggregationService = class {
6110
6299
  const procedureRef = this.db.collection(PROCEDURES_COLLECTION).doc(procedureId);
6111
6300
  batch.update(procedureRef, {
6112
6301
  isActive: false,
6113
- updatedAt: admin10.firestore.FieldValue.serverTimestamp()
6302
+ updatedAt: admin11.firestore.FieldValue.serverTimestamp()
6114
6303
  });
6115
6304
  }
6116
6305
  try {
@@ -6129,15 +6318,15 @@ var PractitionerAggregationService = class {
6129
6318
  };
6130
6319
 
6131
6320
  // src/admin/aggregation/practitioner-invite/practitioner-invite.aggregation.service.ts
6132
- var admin11 = __toESM(require("firebase-admin"));
6321
+ var admin12 = __toESM(require("firebase-admin"));
6133
6322
  var PractitionerInviteAggregationService = class {
6134
6323
  /**
6135
6324
  * Constructor for PractitionerInviteAggregationService.
6136
6325
  * @param firestore Optional Firestore instance. If not provided, it uses the default admin SDK instance.
6137
6326
  * @param mailingService Optional mailing service for sending emails
6138
6327
  */
6139
- constructor(firestore19, mailingService) {
6140
- this.db = firestore19 || admin11.firestore();
6328
+ constructor(firestore20, mailingService) {
6329
+ this.db = firestore20 || admin12.firestore();
6141
6330
  this.mailingService = mailingService;
6142
6331
  Logger.info("[PractitionerInviteAggregationService] Initialized.");
6143
6332
  }
@@ -6434,9 +6623,9 @@ var PractitionerInviteAggregationService = class {
6434
6623
  try {
6435
6624
  const clinicRef = this.db.collection(CLINICS_COLLECTION).doc(clinicId);
6436
6625
  await clinicRef.update({
6437
- doctors: admin11.firestore.FieldValue.arrayUnion(doctorInfo.id),
6438
- doctorsInfo: admin11.firestore.FieldValue.arrayUnion(doctorInfo),
6439
- updatedAt: admin11.firestore.FieldValue.serverTimestamp()
6626
+ doctors: admin12.firestore.FieldValue.arrayUnion(doctorInfo.id),
6627
+ doctorsInfo: admin12.firestore.FieldValue.arrayUnion(doctorInfo),
6628
+ updatedAt: admin12.firestore.FieldValue.serverTimestamp()
6440
6629
  });
6441
6630
  Logger.info(
6442
6631
  `[PractitionerInviteAggService] Successfully added practitioner ${doctorInfo.id} to clinic ${clinicId}`
@@ -6471,7 +6660,7 @@ var PractitionerInviteAggregationService = class {
6471
6660
  const updatedDoctorsInfo = [...filteredDoctorsInfo, doctorInfo];
6472
6661
  await clinicRef.update({
6473
6662
  doctorsInfo: updatedDoctorsInfo,
6474
- updatedAt: admin11.firestore.FieldValue.serverTimestamp()
6663
+ updatedAt: admin12.firestore.FieldValue.serverTimestamp()
6475
6664
  });
6476
6665
  Logger.info(
6477
6666
  `[PractitionerInviteAggService] Successfully updated practitioner ${doctorInfo.id} info in clinic ${clinicId}`
@@ -6506,14 +6695,14 @@ var PractitionerInviteAggregationService = class {
6506
6695
  clinicId: clinicInfo.id,
6507
6696
  workingHours: invite.proposedWorkingHours,
6508
6697
  isActive: true,
6509
- createdAt: admin11.firestore.Timestamp.now(),
6510
- updatedAt: admin11.firestore.Timestamp.now()
6698
+ createdAt: admin12.firestore.Timestamp.now(),
6699
+ updatedAt: admin12.firestore.Timestamp.now()
6511
6700
  };
6512
6701
  await practitionerRef.update({
6513
- clinics: admin11.firestore.FieldValue.arrayUnion(clinicInfo.id),
6514
- clinicsInfo: admin11.firestore.FieldValue.arrayUnion(clinicInfo),
6515
- clinicWorkingHours: admin11.firestore.FieldValue.arrayUnion(workingHours),
6516
- updatedAt: admin11.firestore.FieldValue.serverTimestamp()
6702
+ clinics: admin12.firestore.FieldValue.arrayUnion(clinicInfo.id),
6703
+ clinicsInfo: admin12.firestore.FieldValue.arrayUnion(clinicInfo),
6704
+ clinicWorkingHours: admin12.firestore.FieldValue.arrayUnion(workingHours),
6705
+ updatedAt: admin12.firestore.FieldValue.serverTimestamp()
6517
6706
  });
6518
6707
  Logger.info(
6519
6708
  `[PractitionerInviteAggService] Successfully added clinic ${clinicInfo.id} to practitioner ${practitionerId}`
@@ -6550,7 +6739,7 @@ var PractitionerInviteAggregationService = class {
6550
6739
  ...wh,
6551
6740
  workingHours: invite.proposedWorkingHours,
6552
6741
  isActive: true,
6553
- updatedAt: admin11.firestore.Timestamp.now()
6742
+ updatedAt: admin12.firestore.Timestamp.now()
6554
6743
  };
6555
6744
  }
6556
6745
  return wh;
@@ -6560,13 +6749,13 @@ var PractitionerInviteAggregationService = class {
6560
6749
  clinicId: invite.clinicId,
6561
6750
  workingHours: invite.proposedWorkingHours,
6562
6751
  isActive: true,
6563
- createdAt: admin11.firestore.Timestamp.now(),
6564
- updatedAt: admin11.firestore.Timestamp.now()
6752
+ createdAt: admin12.firestore.Timestamp.now(),
6753
+ updatedAt: admin12.firestore.Timestamp.now()
6565
6754
  });
6566
6755
  }
6567
6756
  await practitionerRef.update({
6568
6757
  clinicWorkingHours: updatedWorkingHours,
6569
- updatedAt: admin11.firestore.FieldValue.serverTimestamp()
6758
+ updatedAt: admin12.firestore.FieldValue.serverTimestamp()
6570
6759
  });
6571
6760
  Logger.info(
6572
6761
  `[PractitionerInviteAggService] Successfully updated working hours for practitioner ${practitionerId} at clinic ${invite.clinicId}`
@@ -6643,8 +6832,8 @@ var PractitionerInviteAggregationService = class {
6643
6832
  var _a, _b, _c, _d, _e, _f;
6644
6833
  if (!this.mailingService) return;
6645
6834
  try {
6646
- const admin19 = await this.fetchClinicAdminById(invite.invitedBy);
6647
- if (!admin19) {
6835
+ const admin20 = await this.fetchClinicAdminById(invite.invitedBy);
6836
+ if (!admin20) {
6648
6837
  Logger.warn(
6649
6838
  `[PractitionerInviteAggService] Admin ${invite.invitedBy} not found, using clinic contact email as fallback`
6650
6839
  );
@@ -6682,7 +6871,7 @@ var PractitionerInviteAggregationService = class {
6682
6871
  );
6683
6872
  return;
6684
6873
  }
6685
- const adminName = `${admin19.contactInfo.firstName} ${admin19.contactInfo.lastName}`;
6874
+ const adminName = `${admin20.contactInfo.firstName} ${admin20.contactInfo.lastName}`;
6686
6875
  const notificationData = {
6687
6876
  invite,
6688
6877
  practitioner: {
@@ -6698,7 +6887,7 @@ var PractitionerInviteAggregationService = class {
6698
6887
  clinic: {
6699
6888
  name: clinic.name,
6700
6889
  adminName,
6701
- adminEmail: admin19.contactInfo.email
6890
+ adminEmail: admin20.contactInfo.email
6702
6891
  // Use the specific admin's email
6703
6892
  },
6704
6893
  context: {
@@ -6734,8 +6923,8 @@ var PractitionerInviteAggregationService = class {
6734
6923
  var _a, _b, _c, _d, _e, _f;
6735
6924
  if (!this.mailingService) return;
6736
6925
  try {
6737
- const admin19 = await this.fetchClinicAdminById(invite.invitedBy);
6738
- if (!admin19) {
6926
+ const admin20 = await this.fetchClinicAdminById(invite.invitedBy);
6927
+ if (!admin20) {
6739
6928
  Logger.warn(
6740
6929
  `[PractitionerInviteAggService] Admin ${invite.invitedBy} not found, using clinic contact email as fallback`
6741
6930
  );
@@ -6773,7 +6962,7 @@ var PractitionerInviteAggregationService = class {
6773
6962
  );
6774
6963
  return;
6775
6964
  }
6776
- const adminName = `${admin19.contactInfo.firstName} ${admin19.contactInfo.lastName}`;
6965
+ const adminName = `${admin20.contactInfo.firstName} ${admin20.contactInfo.lastName}`;
6777
6966
  const notificationData = {
6778
6967
  invite,
6779
6968
  practitioner: {
@@ -6787,7 +6976,7 @@ var PractitionerInviteAggregationService = class {
6787
6976
  clinic: {
6788
6977
  name: clinic.name,
6789
6978
  adminName,
6790
- adminEmail: admin19.contactInfo.email
6979
+ adminEmail: admin20.contactInfo.email
6791
6980
  // Use the specific admin's email
6792
6981
  },
6793
6982
  context: {
@@ -6816,11 +7005,11 @@ var PractitionerInviteAggregationService = class {
6816
7005
  };
6817
7006
 
6818
7007
  // src/admin/aggregation/procedure/procedure.aggregation.service.ts
6819
- var admin12 = __toESM(require("firebase-admin"));
7008
+ var admin13 = __toESM(require("firebase-admin"));
6820
7009
  var CALENDAR_SUBCOLLECTION_ID4 = "calendar";
6821
7010
  var ProcedureAggregationService = class {
6822
- constructor(firestore19) {
6823
- this.db = firestore19 || admin12.firestore();
7011
+ constructor(firestore20) {
7012
+ this.db = firestore20 || admin13.firestore();
6824
7013
  }
6825
7014
  /**
6826
7015
  * Adds procedure information to a practitioner when a new procedure is created
@@ -6844,9 +7033,9 @@ var ProcedureAggregationService = class {
6844
7033
  const practitionerRef = this.db.collection(PRACTITIONERS_COLLECTION).doc(practitionerId);
6845
7034
  try {
6846
7035
  const updateData = {
6847
- procedureIds: admin12.firestore.FieldValue.arrayUnion(procedureId),
6848
- proceduresInfo: admin12.firestore.FieldValue.arrayUnion(procedureSummary),
6849
- updatedAt: admin12.firestore.FieldValue.serverTimestamp()
7036
+ procedureIds: admin13.firestore.FieldValue.arrayUnion(procedureId),
7037
+ proceduresInfo: admin13.firestore.FieldValue.arrayUnion(procedureSummary),
7038
+ updatedAt: admin13.firestore.FieldValue.serverTimestamp()
6850
7039
  };
6851
7040
  if (isFreeConsultation) {
6852
7041
  await this.db.runTransaction(async (transaction) => {
@@ -6909,9 +7098,9 @@ var ProcedureAggregationService = class {
6909
7098
  const clinicRef = this.db.collection(CLINICS_COLLECTION).doc(clinicId);
6910
7099
  try {
6911
7100
  await clinicRef.update({
6912
- procedures: admin12.firestore.FieldValue.arrayUnion(procedureId),
6913
- proceduresInfo: admin12.firestore.FieldValue.arrayUnion(procedureSummary),
6914
- updatedAt: admin12.firestore.FieldValue.serverTimestamp()
7101
+ procedures: admin13.firestore.FieldValue.arrayUnion(procedureId),
7102
+ proceduresInfo: admin13.firestore.FieldValue.arrayUnion(procedureSummary),
7103
+ updatedAt: admin13.firestore.FieldValue.serverTimestamp()
6915
7104
  });
6916
7105
  console.log(
6917
7106
  `[ProcedureAggregationService] Successfully added procedure ${procedureId} to clinic ${clinicId}.`
@@ -6963,7 +7152,7 @@ var ProcedureAggregationService = class {
6963
7152
  updatedProceduresInfo.push(procedureSummary);
6964
7153
  transaction.update(practitionerRef, {
6965
7154
  proceduresInfo: updatedProceduresInfo,
6966
- updatedAt: admin12.firestore.FieldValue.serverTimestamp()
7155
+ updatedAt: admin13.firestore.FieldValue.serverTimestamp()
6967
7156
  });
6968
7157
  });
6969
7158
  console.log(
@@ -7016,7 +7205,7 @@ var ProcedureAggregationService = class {
7016
7205
  updatedProceduresInfo.push(procedureSummary);
7017
7206
  transaction.update(clinicRef, {
7018
7207
  proceduresInfo: updatedProceduresInfo,
7019
- updatedAt: admin12.firestore.FieldValue.serverTimestamp()
7208
+ updatedAt: admin13.firestore.FieldValue.serverTimestamp()
7020
7209
  });
7021
7210
  });
7022
7211
  console.log(
@@ -7046,7 +7235,7 @@ var ProcedureAggregationService = class {
7046
7235
  console.log(
7047
7236
  `[ProcedureAggregationService] Querying upcoming calendar events for procedure ${procedureId} to update procedure info.`
7048
7237
  );
7049
- const now = admin12.firestore.Timestamp.now();
7238
+ const now = admin13.firestore.Timestamp.now();
7050
7239
  const calendarEventsQuery = this.db.collectionGroup(CALENDAR_SUBCOLLECTION_ID4).where("procedureId", "==", procedureId).where("eventTime.start", ">", now);
7051
7240
  try {
7052
7241
  const snapshot = await calendarEventsQuery.get();
@@ -7063,7 +7252,7 @@ var ProcedureAggregationService = class {
7063
7252
  );
7064
7253
  batch.update(doc3.ref, {
7065
7254
  procedureInfo,
7066
- updatedAt: admin12.firestore.FieldValue.serverTimestamp()
7255
+ updatedAt: admin13.firestore.FieldValue.serverTimestamp()
7067
7256
  });
7068
7257
  });
7069
7258
  await batch.commit();
@@ -7093,7 +7282,7 @@ var ProcedureAggregationService = class {
7093
7282
  console.log(
7094
7283
  `[ProcedureAggregationService] Querying upcoming calendar events for procedure ${procedureId} to cancel.`
7095
7284
  );
7096
- const now = admin12.firestore.Timestamp.now();
7285
+ const now = admin13.firestore.Timestamp.now();
7097
7286
  const calendarEventsQuery = this.db.collectionGroup(CALENDAR_SUBCOLLECTION_ID4).where("procedureId", "==", procedureId).where("eventTime.start", ">", now);
7098
7287
  try {
7099
7288
  const snapshot = await calendarEventsQuery.get();
@@ -7111,7 +7300,7 @@ var ProcedureAggregationService = class {
7111
7300
  batch.update(doc3.ref, {
7112
7301
  status: "CANCELED",
7113
7302
  cancelReason: "Procedure deleted or inactivated",
7114
- updatedAt: admin12.firestore.FieldValue.serverTimestamp()
7303
+ updatedAt: admin13.firestore.FieldValue.serverTimestamp()
7115
7304
  });
7116
7305
  });
7117
7306
  await batch.commit();
@@ -7168,9 +7357,9 @@ var ProcedureAggregationService = class {
7168
7357
  (p) => p.id !== procedureId
7169
7358
  );
7170
7359
  const updateData = {
7171
- procedureIds: admin12.firestore.FieldValue.arrayRemove(procedureId),
7360
+ procedureIds: admin13.firestore.FieldValue.arrayRemove(procedureId),
7172
7361
  proceduresInfo: updatedProceduresInfo,
7173
- updatedAt: admin12.firestore.FieldValue.serverTimestamp()
7362
+ updatedAt: admin13.firestore.FieldValue.serverTimestamp()
7174
7363
  };
7175
7364
  if (isFreeConsultation && procedureClinicId) {
7176
7365
  const currentFreeConsultations = practitionerData.freeConsultations || {};
@@ -7236,9 +7425,9 @@ var ProcedureAggregationService = class {
7236
7425
  (p) => p.id !== procedureId
7237
7426
  );
7238
7427
  transaction.update(clinicRef, {
7239
- procedures: admin12.firestore.FieldValue.arrayRemove(procedureId),
7428
+ procedures: admin13.firestore.FieldValue.arrayRemove(procedureId),
7240
7429
  proceduresInfo: updatedProceduresInfo,
7241
- updatedAt: admin12.firestore.FieldValue.serverTimestamp()
7430
+ updatedAt: admin13.firestore.FieldValue.serverTimestamp()
7242
7431
  });
7243
7432
  });
7244
7433
  console.log(
@@ -7315,7 +7504,7 @@ var ProcedureAggregationService = class {
7315
7504
  }
7316
7505
  transaction.update(practitionerRef, {
7317
7506
  freeConsultations: updatedFreeConsultations,
7318
- updatedAt: admin12.firestore.FieldValue.serverTimestamp()
7507
+ updatedAt: admin13.firestore.FieldValue.serverTimestamp()
7319
7508
  });
7320
7509
  });
7321
7510
  console.log(
@@ -7332,14 +7521,14 @@ var ProcedureAggregationService = class {
7332
7521
  };
7333
7522
 
7334
7523
  // src/admin/aggregation/reviews/reviews.aggregation.service.ts
7335
- var admin13 = __toESM(require("firebase-admin"));
7524
+ var admin14 = __toESM(require("firebase-admin"));
7336
7525
  var ReviewsAggregationService = class {
7337
7526
  /**
7338
7527
  * Constructor for ReviewsAggregationService.
7339
7528
  * @param firestore Optional Firestore instance. If not provided, it uses the default admin SDK instance.
7340
7529
  */
7341
- constructor(firestore19) {
7342
- this.db = firestore19 || admin13.firestore();
7530
+ constructor(firestore20) {
7531
+ this.db = firestore20 || admin14.firestore();
7343
7532
  }
7344
7533
  /**
7345
7534
  * Process a newly created review and update all related entities
@@ -7482,7 +7671,7 @@ var ReviewsAggregationService = class {
7482
7671
  };
7483
7672
  await this.db.collection(CLINICS_COLLECTION).doc(clinicId).update({
7484
7673
  reviewInfo: updatedReviewInfo2,
7485
- updatedAt: admin13.firestore.FieldValue.serverTimestamp()
7674
+ updatedAt: admin14.firestore.FieldValue.serverTimestamp()
7486
7675
  });
7487
7676
  console.log(
7488
7677
  `[ReviewsAggregationService] Reset review info for clinic: ${clinicId}`
@@ -7521,7 +7710,7 @@ var ReviewsAggregationService = class {
7521
7710
  };
7522
7711
  await this.db.collection(CLINICS_COLLECTION).doc(clinicId).update({
7523
7712
  reviewInfo: updatedReviewInfo,
7524
- updatedAt: admin13.firestore.FieldValue.serverTimestamp()
7713
+ updatedAt: admin14.firestore.FieldValue.serverTimestamp()
7525
7714
  });
7526
7715
  console.log(
7527
7716
  `[ReviewsAggregationService] Updated review info for clinic: ${clinicId}`
@@ -7571,7 +7760,7 @@ var ReviewsAggregationService = class {
7571
7760
  };
7572
7761
  await this.db.collection(PRACTITIONERS_COLLECTION).doc(practitionerId).update({
7573
7762
  reviewInfo: updatedReviewInfo2,
7574
- updatedAt: admin13.firestore.FieldValue.serverTimestamp()
7763
+ updatedAt: admin14.firestore.FieldValue.serverTimestamp()
7575
7764
  });
7576
7765
  await this.updateDoctorInfoInProcedures(practitionerId, 0);
7577
7766
  console.log(
@@ -7611,7 +7800,7 @@ var ReviewsAggregationService = class {
7611
7800
  };
7612
7801
  await this.db.collection(PRACTITIONERS_COLLECTION).doc(practitionerId).update({
7613
7802
  reviewInfo: updatedReviewInfo,
7614
- updatedAt: admin13.firestore.FieldValue.serverTimestamp()
7803
+ updatedAt: admin14.firestore.FieldValue.serverTimestamp()
7615
7804
  });
7616
7805
  await this.updateDoctorInfoInProcedures(
7617
7806
  practitionerId,
@@ -7678,7 +7867,7 @@ var ReviewsAggregationService = class {
7678
7867
  };
7679
7868
  await this.db.collection(PROCEDURES_COLLECTION).doc(procedureId).update({
7680
7869
  reviewInfo: updatedReviewInfo2,
7681
- updatedAt: admin13.firestore.FieldValue.serverTimestamp()
7870
+ updatedAt: admin14.firestore.FieldValue.serverTimestamp()
7682
7871
  });
7683
7872
  console.log(
7684
7873
  `[ReviewsAggregationService] Reset review info for procedure: ${procedureId}`
@@ -7717,7 +7906,7 @@ var ReviewsAggregationService = class {
7717
7906
  };
7718
7907
  await this.db.collection(PROCEDURES_COLLECTION).doc(procedureId).update({
7719
7908
  reviewInfo: updatedReviewInfo,
7720
- updatedAt: admin13.firestore.FieldValue.serverTimestamp()
7909
+ updatedAt: admin14.firestore.FieldValue.serverTimestamp()
7721
7910
  });
7722
7911
  console.log(
7723
7912
  `[ReviewsAggregationService] Updated review info for procedure: ${procedureId}`
@@ -7745,7 +7934,7 @@ var ReviewsAggregationService = class {
7745
7934
  const procedureRef = this.db.collection(PROCEDURES_COLLECTION).doc(docSnapshot.id);
7746
7935
  batch.update(procedureRef, {
7747
7936
  "doctorInfo.rating": rating,
7748
- updatedAt: admin13.firestore.FieldValue.serverTimestamp()
7937
+ updatedAt: admin14.firestore.FieldValue.serverTimestamp()
7749
7938
  });
7750
7939
  });
7751
7940
  await batch.commit();
@@ -7788,7 +7977,7 @@ var ReviewsAggregationService = class {
7788
7977
  practitionerReview: review.practitionerReview,
7789
7978
  procedureReview: review.procedureReview,
7790
7979
  extendedProcedureReviews: review.extendedProcedureReviews,
7791
- updatedAt: admin13.firestore.FieldValue.serverTimestamp()
7980
+ updatedAt: admin14.firestore.FieldValue.serverTimestamp()
7792
7981
  });
7793
7982
  await batch.commit();
7794
7983
  console.log(
@@ -7819,7 +8008,7 @@ var ReviewsAggregationService = class {
7819
8008
  };
7820
8009
 
7821
8010
  // src/admin/analytics/analytics.admin.service.ts
7822
- var admin14 = __toESM(require("firebase-admin"));
8011
+ var admin15 = __toESM(require("firebase-admin"));
7823
8012
 
7824
8013
  // src/services/analytics/analytics.service.ts
7825
8014
  var import_firestore4 = require("firebase/firestore");
@@ -10882,8 +11071,8 @@ var AnalyticsAdminService = class {
10882
11071
  *
10883
11072
  * @param firestore - Admin Firestore instance (optional, defaults to admin.firestore())
10884
11073
  */
10885
- constructor(firestore19) {
10886
- this.db = firestore19 || admin14.firestore();
11074
+ constructor(firestore20) {
11075
+ this.db = firestore20 || admin15.firestore();
10887
11076
  const mockApp = {
10888
11077
  name: "[DEFAULT]",
10889
11078
  options: {},
@@ -10920,12 +11109,12 @@ var AnalyticsAdminService = class {
10920
11109
  }
10921
11110
  if (params.startDate) {
10922
11111
  const startDate = params.startDate instanceof Date ? params.startDate : params.startDate.toDate();
10923
- const startTimestamp = admin14.firestore.Timestamp.fromDate(startDate);
11112
+ const startTimestamp = admin15.firestore.Timestamp.fromDate(startDate);
10924
11113
  query3 = query3.where("appointmentStartTime", ">=", startTimestamp);
10925
11114
  }
10926
11115
  if (params.endDate) {
10927
11116
  const endDate = params.endDate instanceof Date ? params.endDate : params.endDate.toDate();
10928
- const endTimestamp = admin14.firestore.Timestamp.fromDate(endDate);
11117
+ const endTimestamp = admin15.firestore.Timestamp.fromDate(endDate);
10929
11118
  query3 = query3.where("appointmentStartTime", "<=", endTimestamp);
10930
11119
  }
10931
11120
  const snapshot = await query3.get();
@@ -11076,6 +11265,13 @@ var BookingAvailabilityCalculator = class {
11076
11265
  availableIntervals,
11077
11266
  practitionerCalendarEvents
11078
11267
  );
11268
+ if (request.resourceCalendarEventsMap) {
11269
+ availableIntervals = this.applyResourceAvailability(
11270
+ availableIntervals,
11271
+ request.resourceCalendarEventsMap,
11272
+ timeframe
11273
+ );
11274
+ }
11079
11275
  console.log(
11080
11276
  `After all filters, have ${availableIntervals.length} available intervals`
11081
11277
  );
@@ -11481,18 +11677,98 @@ var BookingAvailabilityCalculator = class {
11481
11677
  }
11482
11678
  return result;
11483
11679
  }
11680
+ /**
11681
+ * Apply resource availability constraints to the available intervals.
11682
+ * For each required resource:
11683
+ * - Compute each instance's availability (full timeframe minus its busy events)
11684
+ * - Union all instance availabilities (at least one must be free)
11685
+ * Then intersect all resource availabilities with the current doctor availability.
11686
+ *
11687
+ * @param intervals - Current available intervals (doctor availability)
11688
+ * @param resourceEventsMap - Map of resource data with per-instance calendar events
11689
+ * @param timeframe - Overall timeframe being considered
11690
+ * @returns Intervals where doctor AND all required resources are available
11691
+ */
11692
+ static applyResourceAvailability(intervals, resourceEventsMap, timeframe) {
11693
+ if (!intervals.length) return [];
11694
+ const resourceIds = Object.keys(resourceEventsMap);
11695
+ if (resourceIds.length === 0) return intervals;
11696
+ console.log(
11697
+ `Applying resource availability for ${resourceIds.length} resource(s)`
11698
+ );
11699
+ let result = intervals;
11700
+ for (const resourceId of resourceIds) {
11701
+ const resourceData = resourceEventsMap[resourceId];
11702
+ const resourceAvailability = this.computeResourceAvailability(
11703
+ resourceData.instanceEvents,
11704
+ timeframe
11705
+ );
11706
+ console.log(
11707
+ `Resource "${resourceData.resourceName}" (qty=${resourceData.quantity}): ${resourceAvailability.length} available intervals`
11708
+ );
11709
+ result = this.intersectIntervals(result, resourceAvailability);
11710
+ if (result.length === 0) {
11711
+ console.log(
11712
+ `No availability remaining after applying resource "${resourceData.resourceName}"`
11713
+ );
11714
+ return [];
11715
+ }
11716
+ }
11717
+ return result;
11718
+ }
11719
+ /**
11720
+ * Compute combined availability for a single resource across all its instances.
11721
+ * For each instance, subtract its busy events from the full timeframe.
11722
+ * Then union all instance availabilities — if at least one instance is free, the resource is available.
11723
+ *
11724
+ * @param instanceEvents - Calendar events keyed by instanceId
11725
+ * @param timeframe - Overall timeframe
11726
+ * @returns Combined availability intervals for the resource
11727
+ */
11728
+ static computeResourceAvailability(instanceEvents, timeframe) {
11729
+ const instanceIds = Object.keys(instanceEvents);
11730
+ if (instanceIds.length === 0) {
11731
+ return [{ start: timeframe.start, end: timeframe.end }];
11732
+ }
11733
+ const allInstanceAvailabilities = [];
11734
+ for (const instanceId of instanceIds) {
11735
+ const events = instanceEvents[instanceId];
11736
+ let instanceAvailability = [
11737
+ { start: timeframe.start, end: timeframe.end }
11738
+ ];
11739
+ for (const event of events) {
11740
+ const isBlockingEvent = event.eventType === "blocking" /* BLOCKING */ || event.eventType === "break" /* BREAK */ || event.eventType === "free_day" /* FREE_DAY */;
11741
+ const isActiveBooking = event.status === "pending" /* PENDING */ || event.status === "confirmed" /* CONFIRMED */;
11742
+ if (isBlockingEvent || isActiveBooking) {
11743
+ const busyInterval = {
11744
+ start: event.eventTime.start,
11745
+ end: event.eventTime.end
11746
+ };
11747
+ const newAvailability = [];
11748
+ for (const interval of instanceAvailability) {
11749
+ newAvailability.push(
11750
+ ...this.subtractInterval(interval, busyInterval)
11751
+ );
11752
+ }
11753
+ instanceAvailability = newAvailability;
11754
+ }
11755
+ }
11756
+ allInstanceAvailabilities.push(...instanceAvailability);
11757
+ }
11758
+ return this.mergeOverlappingIntervals(allInstanceAvailabilities);
11759
+ }
11484
11760
  };
11485
11761
  /** Default scheduling interval in minutes if not specified by the clinic */
11486
11762
  BookingAvailabilityCalculator.DEFAULT_INTERVAL_MINUTES = 15;
11487
11763
 
11488
11764
  // src/admin/booking/booking.admin.ts
11489
- var admin16 = __toESM(require("firebase-admin"));
11765
+ var admin17 = __toESM(require("firebase-admin"));
11490
11766
 
11491
11767
  // src/admin/documentation-templates/document-manager.admin.ts
11492
- var admin15 = __toESM(require("firebase-admin"));
11768
+ var admin16 = __toESM(require("firebase-admin"));
11493
11769
  var DocumentManagerAdminService = class {
11494
- constructor(firestore19) {
11495
- this.db = firestore19;
11770
+ constructor(firestore20) {
11771
+ this.db = firestore20;
11496
11772
  }
11497
11773
  /**
11498
11774
  * Adds operations to a Firestore batch to initialize all linked forms for a new appointment
@@ -11595,7 +11871,7 @@ var DocumentManagerAdminService = class {
11595
11871
  };
11596
11872
  }
11597
11873
  const templateIds = technologyTemplates.map((t) => t.templateId);
11598
- const templatesSnapshot = await this.db.collection(DOCUMENTATION_TEMPLATES_COLLECTION).where(admin15.firestore.FieldPath.documentId(), "in", templateIds).get();
11874
+ const templatesSnapshot = await this.db.collection(DOCUMENTATION_TEMPLATES_COLLECTION).where(admin16.firestore.FieldPath.documentId(), "in", templateIds).get();
11599
11875
  const templatesMap = /* @__PURE__ */ new Map();
11600
11876
  templatesSnapshot.forEach((doc3) => {
11601
11877
  templatesMap.set(doc3.id, doc3.data());
@@ -11661,8 +11937,8 @@ var BookingAdmin = class {
11661
11937
  * Creates a new BookingAdmin instance
11662
11938
  * @param firestore - Firestore instance provided by the caller
11663
11939
  */
11664
- constructor(firestore19) {
11665
- this.db = firestore19 || admin16.firestore();
11940
+ constructor(firestore20) {
11941
+ this.db = firestore20 || admin17.firestore();
11666
11942
  this.documentManagerAdmin = new DocumentManagerAdminService(this.db);
11667
11943
  }
11668
11944
  /**
@@ -11675,7 +11951,7 @@ var BookingAdmin = class {
11675
11951
  * @returns Promise resolving to an array of available booking slots
11676
11952
  */
11677
11953
  async getAvailableBookingSlots(clinicId, practitionerId, procedureId, timeframe) {
11678
- var _a;
11954
+ var _a, _b;
11679
11955
  try {
11680
11956
  Logger.info("[BookingAdmin] Starting availability calculation", {
11681
11957
  clinicId,
@@ -11684,8 +11960,8 @@ var BookingAdmin = class {
11684
11960
  timeframeStart: timeframe.start instanceof Date ? timeframe.start.toISOString() : timeframe.start.toDate().toISOString(),
11685
11961
  timeframeEnd: timeframe.end instanceof Date ? timeframe.end.toISOString() : timeframe.end.toDate().toISOString()
11686
11962
  });
11687
- const start = timeframe.start instanceof Date ? admin16.firestore.Timestamp.fromDate(timeframe.start) : timeframe.start;
11688
- const end = timeframe.end instanceof Date ? admin16.firestore.Timestamp.fromDate(timeframe.end) : timeframe.end;
11963
+ const start = timeframe.start instanceof Date ? admin17.firestore.Timestamp.fromDate(timeframe.start) : timeframe.start;
11964
+ const end = timeframe.end instanceof Date ? admin17.firestore.Timestamp.fromDate(timeframe.end) : timeframe.end;
11689
11965
  Logger.debug("[BookingAdmin] Fetching clinic data", { clinicId });
11690
11966
  const clinicDoc = await this.db.collection("clinics").doc(clinicId).get();
11691
11967
  if (!clinicDoc.exists) {
@@ -11745,6 +12021,74 @@ var BookingAdmin = class {
11745
12021
  Logger.debug("[BookingAdmin] Retrieved practitioner calendar events", {
11746
12022
  count: practitionerCalendarEvents.length
11747
12023
  });
12024
+ let resourceCalendarEventsMap;
12025
+ if (procedure.resourceRequirements && procedure.resourceRequirements.length > 0) {
12026
+ Logger.debug(
12027
+ "[BookingAdmin] Procedure has resource requirements, fetching resource data",
12028
+ {
12029
+ resourceRequirementCount: procedure.resourceRequirements.length,
12030
+ resourceIds: procedure.resourceRequirements.map(
12031
+ (r) => r.resourceId
12032
+ )
12033
+ }
12034
+ );
12035
+ resourceCalendarEventsMap = {};
12036
+ for (const requirement of procedure.resourceRequirements) {
12037
+ const resourceDoc = await this.db.collection(CLINICS_COLLECTION).doc(clinicId).collection(RESOURCES_COLLECTION).doc(requirement.resourceId).get();
12038
+ if (!resourceDoc.exists) {
12039
+ Logger.warn(
12040
+ "[BookingAdmin] Required resource not found, skipping",
12041
+ {
12042
+ resourceId: requirement.resourceId,
12043
+ resourceName: requirement.resourceName
12044
+ }
12045
+ );
12046
+ continue;
12047
+ }
12048
+ const resource = resourceDoc.data();
12049
+ if (resource.status !== "active" /* ACTIVE */) {
12050
+ Logger.warn(
12051
+ "[BookingAdmin] Required resource is not active, skipping",
12052
+ {
12053
+ resourceId: requirement.resourceId,
12054
+ resourceStatus: resource.status
12055
+ }
12056
+ );
12057
+ continue;
12058
+ }
12059
+ const instancesSnapshot = await this.db.collection(CLINICS_COLLECTION).doc(clinicId).collection(RESOURCES_COLLECTION).doc(requirement.resourceId).collection(RESOURCE_INSTANCES_SUBCOLLECTION).where("status", "==", "active" /* ACTIVE */).get();
12060
+ const instanceEvents = {};
12061
+ for (const instanceDoc of instancesSnapshot.docs) {
12062
+ const instanceId = instanceDoc.id;
12063
+ const MAX_EVENT_DURATION_MS = 30 * 24 * 60 * 60 * 1e3;
12064
+ const queryStart = admin17.firestore.Timestamp.fromMillis(
12065
+ start.toMillis() - MAX_EVENT_DURATION_MS
12066
+ );
12067
+ const eventsSnapshot = await this.db.collection(CLINICS_COLLECTION).doc(clinicId).collection(RESOURCES_COLLECTION).doc(requirement.resourceId).collection(RESOURCE_INSTANCES_SUBCOLLECTION).doc(instanceId).collection(RESOURCE_CALENDAR_SUBCOLLECTION).where("eventTime.start", ">=", queryStart).where("eventTime.start", "<=", end).orderBy("eventTime.start").get();
12068
+ const events = eventsSnapshot.docs.map((doc3) => ({ ...doc3.data(), id: doc3.id })).filter(
12069
+ (event) => event.eventTime.end.toMillis() > start.toMillis()
12070
+ );
12071
+ instanceEvents[instanceId] = this.convertEventsTimestamps(
12072
+ events
12073
+ );
12074
+ }
12075
+ resourceCalendarEventsMap[requirement.resourceId] = {
12076
+ resourceId: requirement.resourceId,
12077
+ resourceName: requirement.resourceName,
12078
+ quantity: resource.quantity,
12079
+ instanceEvents
12080
+ };
12081
+ Logger.debug("[BookingAdmin] Fetched resource calendar data", {
12082
+ resourceId: requirement.resourceId,
12083
+ resourceName: requirement.resourceName,
12084
+ instanceCount: instancesSnapshot.size,
12085
+ totalEvents: Object.values(instanceEvents).reduce(
12086
+ (sum, events) => sum + events.length,
12087
+ 0
12088
+ )
12089
+ });
12090
+ }
12091
+ }
11748
12092
  const convertedTimeframe = {
11749
12093
  start: this.adminTimestampToClientTimestamp(start),
11750
12094
  end: this.adminTimestampToClientTimestamp(end)
@@ -11758,7 +12102,8 @@ var BookingAdmin = class {
11758
12102
  practitionerCalendarEvents: this.convertEventsTimestamps(
11759
12103
  practitionerCalendarEvents
11760
12104
  ),
11761
- tz: clinic.location.tz || "UTC"
12105
+ tz: clinic.location.tz || "UTC",
12106
+ ...resourceCalendarEventsMap && { resourceCalendarEventsMap }
11762
12107
  };
11763
12108
  Logger.info("[BookingAdmin] Calling availability calculator", {
11764
12109
  calculatorInputReady: true,
@@ -11766,12 +12111,14 @@ var BookingAdmin = class {
11766
12111
  (end.toMillis() - start.toMillis()) / (1e3 * 60 * 60)
11767
12112
  ),
11768
12113
  clinicEventsCount: clinicCalendarEvents.length,
11769
- practitionerEventsCount: practitionerCalendarEvents.length
12114
+ practitionerEventsCount: practitionerCalendarEvents.length,
12115
+ resourceRequirementCount: ((_b = procedure.resourceRequirements) == null ? void 0 : _b.length) || 0,
12116
+ hasResourceData: !!resourceCalendarEventsMap
11770
12117
  });
11771
12118
  const result = BookingAvailabilityCalculator.calculateSlots(request);
11772
12119
  const availableSlotsResult = {
11773
12120
  availableSlots: result.availableSlots.map((slot) => ({
11774
- start: admin16.firestore.Timestamp.fromMillis(slot.start.toMillis())
12121
+ start: admin17.firestore.Timestamp.fromMillis(slot.start.toMillis())
11775
12122
  }))
11776
12123
  };
11777
12124
  Logger.info(
@@ -11834,7 +12181,7 @@ var BookingAdmin = class {
11834
12181
  endTime: end.toDate().toISOString()
11835
12182
  });
11836
12183
  const MAX_EVENT_DURATION_MS = 30 * 24 * 60 * 60 * 1e3;
11837
- const queryStart = admin16.firestore.Timestamp.fromMillis(
12184
+ const queryStart = admin17.firestore.Timestamp.fromMillis(
11838
12185
  start.toMillis() - MAX_EVENT_DURATION_MS
11839
12186
  );
11840
12187
  const eventsRef = this.db.collection(`clinics/${clinicId}/calendar`).where("eventTime.start", ">=", queryStart).where("eventTime.start", "<=", end).orderBy("eventTime.start");
@@ -11890,7 +12237,7 @@ var BookingAdmin = class {
11890
12237
  endTime: end.toDate().toISOString()
11891
12238
  });
11892
12239
  const MAX_EVENT_DURATION_MS = 30 * 24 * 60 * 60 * 1e3;
11893
- const queryStart = admin16.firestore.Timestamp.fromMillis(
12240
+ const queryStart = admin17.firestore.Timestamp.fromMillis(
11894
12241
  start.toMillis() - MAX_EVENT_DURATION_MS
11895
12242
  );
11896
12243
  const eventsRef = this.db.collection(`practitioners/${practitionerId}/calendar`).where("eventTime.start", ">=", queryStart).where("eventTime.start", "<=", end).orderBy("eventTime.start");
@@ -11969,8 +12316,8 @@ var BookingAdmin = class {
11969
12316
  `[BookingAdmin] Orchestrating appointment creation for patient ${data.patientId} by user ${authenticatedUserId}`
11970
12317
  );
11971
12318
  const batch = this.db.batch();
11972
- const adminTsNow = admin16.firestore.Timestamp.now();
11973
- const serverTimestampValue = admin16.firestore.FieldValue.serverTimestamp();
12319
+ const adminTsNow = admin17.firestore.Timestamp.now();
12320
+ const serverTimestampValue = admin17.firestore.FieldValue.serverTimestamp();
11974
12321
  try {
11975
12322
  if (!data.patientId || !data.procedureId || !data.appointmentStartTime || !data.appointmentEndTime) {
11976
12323
  return {
@@ -12067,7 +12414,7 @@ var BookingAdmin = class {
12067
12414
  fullName: `${(patientSensitiveData == null ? void 0 : patientSensitiveData.firstName) || ""} ${(patientSensitiveData == null ? void 0 : patientSensitiveData.lastName) || ""}`.trim() || patientProfileData.displayName,
12068
12415
  email: (patientSensitiveData == null ? void 0 : patientSensitiveData.email) || "",
12069
12416
  phone: (patientSensitiveData == null ? void 0 : patientSensitiveData.phoneNumber) || patientProfileData.phoneNumber || null,
12070
- dateOfBirth: (patientSensitiveData == null ? void 0 : patientSensitiveData.dateOfBirth) || patientProfileData.dateOfBirth || admin16.firestore.Timestamp.now(),
12417
+ dateOfBirth: (patientSensitiveData == null ? void 0 : patientSensitiveData.dateOfBirth) || patientProfileData.dateOfBirth || admin17.firestore.Timestamp.now(),
12071
12418
  gender: (patientSensitiveData == null ? void 0 : patientSensitiveData.gender) || "other" /* OTHER */
12072
12419
  };
12073
12420
  const newAppointmentId = this.db.collection(APPOINTMENTS_COLLECTION).doc().id;
@@ -12149,6 +12496,76 @@ var BookingAdmin = class {
12149
12496
  this.db.collection(CLINICS_COLLECTION).doc(clinicData.id).collection(CALENDAR_COLLECTION).doc(practitionerCalendarEventId),
12150
12497
  clinicCalendarEventData
12151
12498
  );
12499
+ let resourceBookings = [];
12500
+ if (procedure.resourceRequirements && procedure.resourceRequirements.length > 0) {
12501
+ console.log(
12502
+ `[BookingAdmin] Allocating resources for appointment ${newAppointmentId}, ${procedure.resourceRequirements.length} resource(s) required`
12503
+ );
12504
+ for (const requirement of procedure.resourceRequirements) {
12505
+ const instancesSnapshot = await this.db.collection(CLINICS_COLLECTION).doc(clinicData.id).collection(RESOURCES_COLLECTION).doc(requirement.resourceId).collection(RESOURCE_INSTANCES_SUBCOLLECTION).where("status", "==", "active" /* ACTIVE */).orderBy("index").get();
12506
+ if (instancesSnapshot.empty) {
12507
+ return {
12508
+ success: false,
12509
+ error: `Resource "${requirement.resourceName}" has no active instances available.`
12510
+ };
12511
+ }
12512
+ let allocatedInstance = null;
12513
+ for (const instanceDoc of instancesSnapshot.docs) {
12514
+ const instance = {
12515
+ ...instanceDoc.data(),
12516
+ id: instanceDoc.id
12517
+ };
12518
+ const overlappingEventsSnapshot = await this.db.collection(CLINICS_COLLECTION).doc(clinicData.id).collection(RESOURCES_COLLECTION).doc(requirement.resourceId).collection(RESOURCE_INSTANCES_SUBCOLLECTION).doc(instance.id).collection(RESOURCE_CALENDAR_SUBCOLLECTION).where("eventTime.start", "<", data.appointmentEndTime).where("status", "in", [
12519
+ "pending" /* PENDING */,
12520
+ "confirmed" /* CONFIRMED */,
12521
+ "checked_in" /* CHECKED_IN */,
12522
+ "in_progress" /* IN_PROGRESS */
12523
+ ]).get();
12524
+ const hasOverlap = overlappingEventsSnapshot.docs.some((doc3) => {
12525
+ const event = doc3.data();
12526
+ return event.eventTime.end.toMillis() > data.appointmentStartTime.toMillis();
12527
+ });
12528
+ if (!hasOverlap) {
12529
+ allocatedInstance = instance;
12530
+ break;
12531
+ }
12532
+ }
12533
+ if (!allocatedInstance) {
12534
+ return {
12535
+ success: false,
12536
+ error: `Resource "${requirement.resourceName}" is not available at the selected time. All instances are booked.`
12537
+ };
12538
+ }
12539
+ const resourceCalendarEventRef = this.db.collection(CLINICS_COLLECTION).doc(clinicData.id).collection(RESOURCES_COLLECTION).doc(requirement.resourceId).collection(RESOURCE_INSTANCES_SUBCOLLECTION).doc(allocatedInstance.id).collection(RESOURCE_CALENDAR_SUBCOLLECTION).doc();
12540
+ const resourceCalendarEventData = {
12541
+ id: resourceCalendarEventRef.id,
12542
+ resourceId: requirement.resourceId,
12543
+ resourceInstanceId: allocatedInstance.id,
12544
+ clinicBranchId: clinicData.id,
12545
+ eventType: "resource_booking" /* RESOURCE_BOOKING */,
12546
+ appointmentId: newAppointmentId,
12547
+ procedureId: procedure.id,
12548
+ practitionerId: practitionerData.id,
12549
+ patientId: data.patientId,
12550
+ eventTime: eventTimeForCalendarEvents,
12551
+ status: initialCalendarEventStatus,
12552
+ eventName: `${procedure.name} - ${allocatedInstance.label}`,
12553
+ createdAt: serverTimestampValue,
12554
+ updatedAt: serverTimestampValue
12555
+ };
12556
+ batch.set(resourceCalendarEventRef, resourceCalendarEventData);
12557
+ resourceBookings.push({
12558
+ resourceId: requirement.resourceId,
12559
+ resourceName: requirement.resourceName,
12560
+ resourceInstanceId: allocatedInstance.id,
12561
+ resourceInstanceLabel: allocatedInstance.label,
12562
+ calendarEventId: resourceCalendarEventRef.id
12563
+ });
12564
+ console.log(
12565
+ `[BookingAdmin] Allocated resource "${requirement.resourceName}" \u2192 instance "${allocatedInstance.label}" (${allocatedInstance.id})`
12566
+ );
12567
+ }
12568
+ }
12152
12569
  let initializedFormsInfo = [];
12153
12570
  let pendingUserFormTemplateIds = [];
12154
12571
  let allLinkedFormTemplateIds = [];
@@ -12231,6 +12648,7 @@ var BookingAdmin = class {
12231
12648
  isRecurring: false,
12232
12649
  recurringAppointmentId: null,
12233
12650
  isArchived: false,
12651
+ ...resourceBookings.length > 0 && { resourceBookings },
12234
12652
  createdAt: adminTsNow,
12235
12653
  updatedAt: adminTsNow
12236
12654
  };
@@ -12332,7 +12750,7 @@ var BookingAdmin = class {
12332
12750
  };
12333
12751
 
12334
12752
  // src/admin/free-consultation/free-consultation-utils.admin.ts
12335
- var admin17 = __toESM(require("firebase-admin"));
12753
+ var admin18 = __toESM(require("firebase-admin"));
12336
12754
 
12337
12755
  // src/backoffice/types/category.types.ts
12338
12756
  var CATEGORIES_COLLECTION = "backoffice_categories";
@@ -12345,10 +12763,10 @@ var TECHNOLOGIES_COLLECTION = "technologies";
12345
12763
 
12346
12764
  // src/admin/free-consultation/free-consultation-utils.admin.ts
12347
12765
  async function freeConsultationInfrastructure(db) {
12348
- const firestore19 = db || admin17.firestore();
12766
+ const firestore20 = db || admin18.firestore();
12349
12767
  try {
12350
12768
  console.log("[freeConsultationInfrastructure] Checking free consultation infrastructure...");
12351
- const technologyRef = firestore19.collection(TECHNOLOGIES_COLLECTION).doc("free-consultation-tech");
12769
+ const technologyRef = firestore20.collection(TECHNOLOGIES_COLLECTION).doc("free-consultation-tech");
12352
12770
  const technologyDoc = await technologyRef.get();
12353
12771
  if (technologyDoc.exists) {
12354
12772
  console.log(
@@ -12357,7 +12775,7 @@ async function freeConsultationInfrastructure(db) {
12357
12775
  return true;
12358
12776
  }
12359
12777
  console.log("[freeConsultationInfrastructure] Creating free consultation infrastructure...");
12360
- await createFreeConsultationInfrastructure(firestore19);
12778
+ await createFreeConsultationInfrastructure(firestore20);
12361
12779
  console.log(
12362
12780
  "[freeConsultationInfrastructure] Successfully created free consultation infrastructure"
12363
12781
  );
@@ -12554,8 +12972,8 @@ var PractitionerInviteMailingService = class extends BaseMailingService {
12554
12972
  * @param firestore Firestore instance provided by the caller
12555
12973
  * @param mailgunClient Mailgun client instance (mailgun.js v10+) provided by the caller
12556
12974
  */
12557
- constructor(firestore19, mailgunClient) {
12558
- super(firestore19, mailgunClient);
12975
+ constructor(firestore20, mailgunClient) {
12976
+ super(firestore20, mailgunClient);
12559
12977
  this.DEFAULT_REGISTRATION_URL = "https://metaesthetics.net/register";
12560
12978
  this.DEFAULT_SUBJECT = "You've Been Invited to Join as a Practitioner";
12561
12979
  this.DEFAULT_MAILGUN_DOMAIN = "mg.metaesthetics.net";
@@ -13418,8 +13836,8 @@ var ExistingPractitionerInviteMailingService = class extends BaseMailingService
13418
13836
  * @param firestore Firestore instance provided by the caller
13419
13837
  * @param mailgunClient Mailgun client instance (mailgun.js v10+) provided by the caller
13420
13838
  */
13421
- constructor(firestore19, mailgunClient) {
13422
- super(firestore19, mailgunClient);
13839
+ constructor(firestore20, mailgunClient) {
13840
+ super(firestore20, mailgunClient);
13423
13841
  this.DEFAULT_MAILGUN_DOMAIN = "mg.metaesthetics.net";
13424
13842
  this.DEFAULT_FROM_ADDRESS = "Metaesthetics <no-reply@mg.metaesthetics.net>";
13425
13843
  }
@@ -13901,8 +14319,8 @@ var PatientInviteMailingService = class extends BaseMailingService {
13901
14319
  * @param firestore - Firestore instance provided by the caller
13902
14320
  * @param mailgunClient - Mailgun client instance (mailgun.js v10+) provided by the caller
13903
14321
  */
13904
- constructor(firestore19, mailgunClient) {
13905
- super(firestore19, mailgunClient);
14322
+ constructor(firestore20, mailgunClient) {
14323
+ super(firestore20, mailgunClient);
13906
14324
  this.DEFAULT_REGISTRATION_URL = "https://metaesthetics.net/patient/register";
13907
14325
  this.DEFAULT_SUBJECT = "Claim Your Patient Profile - Metaesthetics";
13908
14326
  this.DEFAULT_MAILGUN_DOMAIN = "mg.metaesthetics.net";
@@ -14377,8 +14795,8 @@ var ClinicWelcomeMailingService = class extends BaseMailingService {
14377
14795
  * @param firestore - Firestore instance provided by the caller
14378
14796
  * @param mailgunClient - Mailgun client instance (mailgun.js v10+) provided by the caller
14379
14797
  */
14380
- constructor(firestore19, mailgunClient) {
14381
- super(firestore19, mailgunClient);
14798
+ constructor(firestore20, mailgunClient) {
14799
+ super(firestore20, mailgunClient);
14382
14800
  this.DEFAULT_DASHBOARD_URL = "https://app.metaesthetics.net/dashboard";
14383
14801
  this.DEFAULT_SUPPORT_EMAIL = "support@metaesthetics.net";
14384
14802
  this.DEFAULT_SUBJECT = "Welcome to Metaesthetics - Your Clinic Registration is Complete";
@@ -14548,14 +14966,14 @@ var ClinicWelcomeMailingService = class extends BaseMailingService {
14548
14966
  };
14549
14967
 
14550
14968
  // src/admin/users/user-profile.admin.ts
14551
- var admin18 = __toESM(require("firebase-admin"));
14969
+ var admin19 = __toESM(require("firebase-admin"));
14552
14970
  var UserProfileAdminService = class {
14553
14971
  /**
14554
14972
  * Constructor for UserProfileAdminService
14555
14973
  * @param firestore Optional Firestore instance. If not provided, uses the default admin SDK instance.
14556
14974
  */
14557
- constructor(firestore19) {
14558
- this.db = firestore19 || admin18.firestore();
14975
+ constructor(firestore20) {
14976
+ this.db = firestore20 || admin19.firestore();
14559
14977
  }
14560
14978
  /**
14561
14979
  * Creates a blank user profile with minimal information
@@ -14572,9 +14990,9 @@ var UserProfileAdminService = class {
14572
14990
  roles: [],
14573
14991
  // Empty roles array as requested
14574
14992
  isAnonymous: authUserData.isAnonymous,
14575
- createdAt: admin18.firestore.FieldValue.serverTimestamp(),
14576
- updatedAt: admin18.firestore.FieldValue.serverTimestamp(),
14577
- lastLoginAt: admin18.firestore.FieldValue.serverTimestamp()
14993
+ createdAt: admin19.firestore.FieldValue.serverTimestamp(),
14994
+ updatedAt: admin19.firestore.FieldValue.serverTimestamp(),
14995
+ lastLoginAt: admin19.firestore.FieldValue.serverTimestamp()
14578
14996
  };
14579
14997
  try {
14580
14998
  const userRef = this.db.collection(USERS_COLLECTION).doc(authUserData.uid);
@@ -14650,8 +15068,8 @@ var UserProfileAdminService = class {
14650
15068
  clinics: mergedProfileData.clinics || [],
14651
15069
  doctorIds: mergedProfileData.doctorIds || [],
14652
15070
  clinicIds: mergedProfileData.clinicIds || [],
14653
- createdAt: admin18.firestore.FieldValue.serverTimestamp(),
14654
- updatedAt: admin18.firestore.FieldValue.serverTimestamp()
15071
+ createdAt: admin19.firestore.FieldValue.serverTimestamp(),
15072
+ updatedAt: admin19.firestore.FieldValue.serverTimestamp()
14655
15073
  };
14656
15074
  await patientProfileRef.set(patientProfileData);
14657
15075
  patientProfile = {
@@ -14690,8 +15108,8 @@ var UserProfileAdminService = class {
14690
15108
  };
14691
15109
  const sensitiveInfoData = {
14692
15110
  ...mergedSensitiveData,
14693
- createdAt: admin18.firestore.FieldValue.serverTimestamp(),
14694
- updatedAt: admin18.firestore.FieldValue.serverTimestamp()
15111
+ createdAt: admin19.firestore.FieldValue.serverTimestamp(),
15112
+ updatedAt: admin19.firestore.FieldValue.serverTimestamp()
14695
15113
  // Leave dateOfBirth as is
14696
15114
  };
14697
15115
  await sensitiveInfoRef.set(sensitiveInfoData);
@@ -14717,7 +15135,7 @@ var UserProfileAdminService = class {
14717
15135
  contraindications: [],
14718
15136
  allergies: [],
14719
15137
  currentMedications: [],
14720
- lastUpdated: admin18.firestore.FieldValue.serverTimestamp(),
15138
+ lastUpdated: admin19.firestore.FieldValue.serverTimestamp(),
14721
15139
  updatedBy: userId
14722
15140
  };
14723
15141
  await medicalInfoRef.set(medicalInfoData);
@@ -14734,14 +15152,14 @@ var UserProfileAdminService = class {
14734
15152
  const batch = this.db.batch();
14735
15153
  if (!userData.roles.includes("patient" /* PATIENT */)) {
14736
15154
  batch.update(userRef, {
14737
- roles: admin18.firestore.FieldValue.arrayUnion("patient" /* PATIENT */),
14738
- updatedAt: admin18.firestore.FieldValue.serverTimestamp()
15155
+ roles: admin19.firestore.FieldValue.arrayUnion("patient" /* PATIENT */),
15156
+ updatedAt: admin19.firestore.FieldValue.serverTimestamp()
14739
15157
  });
14740
15158
  }
14741
15159
  if (!userData.patientProfile) {
14742
15160
  batch.update(userRef, {
14743
15161
  patientProfile: patientProfileId,
14744
- updatedAt: admin18.firestore.FieldValue.serverTimestamp()
15162
+ updatedAt: admin19.firestore.FieldValue.serverTimestamp()
14745
15163
  });
14746
15164
  }
14747
15165
  await batch.commit();
@@ -14782,8 +15200,8 @@ var UserProfileAdminService = class {
14782
15200
  const userData = userDoc.data();
14783
15201
  if (!userData.roles.includes("clinic_admin" /* CLINIC_ADMIN */)) {
14784
15202
  await userRef.update({
14785
- roles: admin18.firestore.FieldValue.arrayUnion("clinic_admin" /* CLINIC_ADMIN */),
14786
- updatedAt: admin18.firestore.FieldValue.serverTimestamp()
15203
+ roles: admin19.firestore.FieldValue.arrayUnion("clinic_admin" /* CLINIC_ADMIN */),
15204
+ updatedAt: admin19.firestore.FieldValue.serverTimestamp()
14787
15205
  });
14788
15206
  }
14789
15207
  const updatedUserDoc = await userRef.get();
@@ -14814,8 +15232,8 @@ var UserProfileAdminService = class {
14814
15232
  const userData = userDoc.data();
14815
15233
  if (!userData.roles.includes("practitioner" /* PRACTITIONER */)) {
14816
15234
  await userRef.update({
14817
- roles: admin18.firestore.FieldValue.arrayUnion("practitioner" /* PRACTITIONER */),
14818
- updatedAt: admin18.firestore.FieldValue.serverTimestamp()
15235
+ roles: admin19.firestore.FieldValue.arrayUnion("practitioner" /* PRACTITIONER */),
15236
+ updatedAt: admin19.firestore.FieldValue.serverTimestamp()
14819
15237
  });
14820
15238
  }
14821
15239
  const updatedUserDoc = await userRef.get();
@@ -14879,6 +15297,7 @@ TimestampUtils.enableServerMode();
14879
15297
  PractitionerTokenStatus,
14880
15298
  ProcedureAggregationService,
14881
15299
  REVENUE_ANALYTICS_SUBCOLLECTION,
15300
+ ResourceCalendarAdminService,
14882
15301
  ReviewsAggregationService,
14883
15302
  SubscriptionStatus,
14884
15303
  TIME_EFFICIENCY_ANALYTICS_SUBCOLLECTION,