@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
@@ -1,518 +1,525 @@
1
- import { Timestamp, FieldValue } from 'firebase/firestore';
2
- import { ClinicInfo, PractitionerProfileInfo, PatientProfileInfo } from '../profile';
3
- import { ProcedureSummaryInfo } from '../procedure';
4
- import { Currency, type PricingMeasure } from '../../backoffice/types/static/pricing.types';
5
- import { BlockingCondition } from '../../backoffice/types/static/blocking-condition.types';
6
- import { Requirement } from '../../backoffice/types/requirement.types';
7
- import { FilledDocumentStatus } from '../documentation-templates';
8
- import type { ContraindicationDynamic, ProcedureFamily } from '../../backoffice';
9
- import type { MediaResource } from '../../services/media/media.service';
10
- import { string } from 'zod/v4';
11
-
12
- /**
13
- * Enum defining the possible statuses of an appointment.
14
- */
15
- export enum AppointmentStatus {
16
- PENDING = 'pending', // Initial state after booking, before confirmation (if applicable)
17
- CONFIRMED = 'confirmed', // Confirmed by clinic/practitioner
18
- CHECKED_IN = 'checked_in', // Patient has arrived
19
- IN_PROGRESS = 'in_progress', // Procedure has started
20
- COMPLETED = 'completed', // Procedure finished successfully
21
- CANCELED_PATIENT = 'canceled_patient', // Canceled by the patient
22
- CANCELED_PATIENT_RESCHEDULED = 'canceled_patient_rescheduled', // Canceled by the patient and rescheduled by the clinic
23
- CANCELED_CLINIC = 'canceled_clinic', // Canceled by the clinic/practitioner
24
- NO_SHOW = 'no_show', // Patient did not attend
25
- RESCHEDULED_BY_CLINIC = 'rescheduled_by_clinic', // When appointment is rescheduled by the clinic, waiting for patient confirmation or cancellation (when reschedule is accepted, status goes to confirmed, if not accepted, then status goes to canceled_patient_rescheduled)
26
- }
27
-
28
- /**
29
- * Enum defining the payment status of an appointment.
30
- */
31
- export enum PaymentStatus {
32
- UNPAID = 'unpaid',
33
- PAID = 'paid',
34
- PARTIALLY_PAID = 'partially_paid',
35
- REFUNDED = 'refunded',
36
- NOT_APPLICABLE = 'not_applicable', // For free services or other scenarios
37
- }
38
-
39
- /**
40
- * Enum for different types of media that can be attached to an appointment.
41
- */
42
- export enum MediaType {
43
- BEFORE_PHOTO = 'before_photo',
44
- AFTER_PHOTO = 'after_photo',
45
- CONSENT_SCAN = 'consent_scan',
46
- OTHER_DOCUMENT = 'other_document',
47
- }
48
-
49
- /**
50
- * Interface to describe a media file linked to an appointment.
51
- */
52
- export interface AppointmentMediaItem {
53
- id: string; // Auto-generated unique ID for the media item
54
- type: MediaType;
55
- url: string; // Cloud Storage URL
56
- fileName?: string;
57
- uploadedAt: Timestamp;
58
- uploadedBy: string; // User ID (patient, practitioner, or clinic_admin)
59
- description?: string;
60
- }
61
-
62
- /**
63
- * Interface for procedure-specific information
64
- */
65
- export interface ProcedureExtendedInfo {
66
- id: string;
67
- name: string;
68
- description: string;
69
- cost: number;
70
- duration: number;
71
- procedureFamily: ProcedureFamily;
72
- procedureCategoryId: string;
73
- procedureCategoryName: string;
74
- procedureSubCategoryId: string;
75
- procedureSubCategoryName: string;
76
- procedureTechnologyId: string;
77
- procedureTechnologyName: string;
78
- procedureProductBrandId: string;
79
- procedureProductBrandName: string;
80
- procedureProducts: Array<{
81
- productId: string;
82
- productName: string;
83
- brandId: string;
84
- brandName: string;
85
- }>;
86
- }
87
-
88
- /**
89
- * Interface to describe a filled form linked to an appointment.
90
- */
91
- export interface LinkedFormInfo {
92
- formId: string; // ID of the FilledDocument
93
- templateId: string;
94
- templateVersion: number;
95
- title: string; // For display, usually from DocumentTemplate.title
96
- isUserForm: boolean;
97
- isRequired?: boolean;
98
- sortingOrder?: number;
99
- status: FilledDocumentStatus; // Status of the filled form (e.g., draft, completed, signed)
100
- path: string; // Full Firestore path to the filled document (e.g., appointments/{aid}/user-forms/{fid})
101
- submittedAt?: Timestamp;
102
- completedAt?: Timestamp; // When the form reached a final state like 'completed' or 'signed'
103
- procedureId?: string; // ID of the procedure this form belongs to (for extended procedure forms)
104
- }
105
-
106
- /**
107
- * Interface for summarized patient review information linked to an appointment.
108
- */
109
- export interface PatientReviewInfo {
110
- reviewId: string; // ID of the full review document/record if stored elsewhere
111
- rating: number; // e.g., 1-5 stars
112
- comment?: string; // A short snippet or the full comment
113
- reviewedAt: Timestamp;
114
- }
115
-
116
- /**
117
- * Interface for before/after photos and notes per zone
118
- */
119
- export interface BeforeAfterPerZone {
120
- /** URL for before photo or null if not available */
121
- before: MediaResource | null;
122
- /** URL for after photo or null if not available */
123
- after: MediaResource | null;
124
- /** Optional note for the before photo */
125
- beforeNote?: string | null;
126
- /** Optional note for the after photo */
127
- afterNote?: string | null;
128
- /** Whether this photo pair (before AND after) should be visible to the patient */
129
- showToPatient?: boolean;
130
- /** Whether the before note should be visible to the patient */
131
- beforeNoteVisibleToPatient?: boolean;
132
- /** Whether the after note should be visible to the patient */
133
- afterNoteVisibleToPatient?: boolean;
134
- /** Timestamp when visibility was last updated */
135
- visibilityUpdatedAt?: Timestamp;
136
- /** ID of the doctor who last updated visibility */
137
- visibilityUpdatedBy?: string;
138
- }
139
-
140
- /**
141
- * Interface for zone photo upload data
142
- */
143
- export interface ZonePhotoUploadData {
144
- appointmentId: string;
145
- zoneId: string;
146
- photoType: 'before' | 'after';
147
- file: File | Blob;
148
- notes?: string;
149
- }
150
-
151
- /**
152
- * Interface for zone item data (products or notes per zone)
153
- */
154
- export interface ZoneItemData {
155
- productId?: string;
156
- productName?: string;
157
- productBrandId?: string;
158
- productBrandName?: string;
159
- belongingProcedureId: string;
160
- type: 'item' | 'note';
161
- stage?: 'before' | 'after'; // Stage of the note/item: 'before' for planning notes, 'after' for treatment notes
162
- price?: number;
163
- currency?: Currency;
164
- unitOfMeasurement?: PricingMeasure;
165
- priceOverrideAmount?: number; // If set, takes precedence over price
166
- quantity?: number;
167
- parentZone: string; // Zone key in format "category.zone" (e.g., "face.forehead")
168
- subzones: string[];
169
- notes?: string;
170
- notesVisibleToPatient?: boolean; // Whether notes are visible to patient (privacy-first, default false)
171
- subtotal?: number;
172
- ionNumber?: string | null; // Batch/Lot number - can be null to clear/delete
173
- expiryDate?: string | null; // ISO date string (YYYY-MM-DD) - can be null to clear/delete
174
- createdAt?: string; // ISO timestamp
175
- updatedAt?: string; // ISO timestamp
176
- }
177
-
178
- /**
179
- * @deprecated Use ZoneItemData instead
180
- */
181
- export interface BillingPerZone {
182
- Product: string;
183
- ProductId: string | null;
184
- Quantity: number;
185
- UnitOfMeasurement: PricingMeasure;
186
- UnitPrice: number;
187
- UnitCurency: Currency;
188
- Subtotal: number;
189
- Note: string | null;
190
- IonNumber: string | null;
191
- }
192
-
193
- /**
194
- * Interface for final billing calculations of the appointment
195
- */
196
- export interface FinalBilling {
197
- /** Total of all subtotals from all zones */
198
- subtotalAll: number;
199
- /** Overall discount applied to the subtotal */
200
- discount?: {
201
- type: 'percentage' | 'fixed';
202
- value: number; // e.g., 10 for 10% or 50 for CHF 50
203
- amount: number; // calculated discount in currency
204
- };
205
- /** Subtotal after discount (subtotalAll - discount.amount) */
206
- discountedSubtotal?: number;
207
- /** Tax rate as percentage (e.g., 0.20 for 20%) */
208
- taxRate: number;
209
- /** Calculated tax amount */
210
- taxPrice: number;
211
- /** Final price including tax */
212
- finalPrice: number;
213
- /** Currency for the final billing */
214
- currency: Currency;
215
- }
216
-
217
- /**
218
- * Interface for product metadata in appointment
219
- */
220
- export interface AppointmentProductMetadata {
221
- productId: string;
222
- productName: string;
223
- brandId: string;
224
- brandName: string;
225
- procedureId: string;
226
- price: number;
227
- currency: Currency;
228
- unitOfMeasurement: PricingMeasure;
229
- }
230
-
231
- /**
232
- * Interface for extended procedures in appointment
233
- */
234
- export interface ExtendedProcedureInfo {
235
- procedureId: string;
236
- procedureName: string;
237
- procedureDescription?: string;
238
- procedurePrice?: number;
239
- procedureFamily?: ProcedureFamily;
240
- procedureCategoryId: string;
241
- procedureCategoryName: string;
242
- procedureSubCategoryId: string;
243
- procedureSubCategoryName: string;
244
- procedureTechnologyId: string;
245
- procedureTechnologyName: string;
246
- procedureProducts: Array<{
247
- productId: string;
248
- productName: string;
249
- brandId: string;
250
- brandName: string;
251
- }>;
252
- }
253
-
254
- export interface RecommendedProcedure {
255
- procedure: ExtendedProcedureInfo;
256
- note: string;
257
- timeframe: {
258
- value: number;
259
- unit: 'day' | 'week' | 'month' | 'year';
260
- };
261
- }
262
-
263
- /**
264
- * Interface for appointment metadata containing zone-specific information
265
- */
266
- export interface AppointmentMetadata {
267
- selectedZones: string[] | null;
268
- zonePhotos: Record<string, BeforeAfterPerZone[]> | null;
269
- zonesData?: Record<string, ZoneItemData[]> | null;
270
- appointmentProducts?: AppointmentProductMetadata[];
271
- extendedProcedures?: ExtendedProcedureInfo[];
272
- recommendedProcedures: RecommendedProcedure[]
273
- finalbilling: FinalBilling | null;
274
- /** Final treatment notes shared with patient */
275
- finalizationNotesShared?: string | null;
276
- /** Final treatment notes for internal use only (not shared with patient) */
277
- finalizationNotesInternal?: string | null;
278
- /**
279
- * @deprecated Use finalizationNotesShared instead. Kept for backward compatibility during migration.
280
- */
281
- finalizationNotes?: string | null;
282
-
283
- /**
284
- * @deprecated Use zonesData instead
285
- */
286
- zoneBilling?: Record<string, BillingPerZone> | null;
287
- }
288
-
289
- /**
290
- * Represents a booked appointment, aggregating key information and relevant procedure rules.
291
- */
292
- export interface Appointment {
293
- /** Unique identifier for the appointment */
294
- id: string;
295
- /** Reference to the associated CalendarEvent */
296
- calendarEventId: string;
297
-
298
- /** ID of the clinic branch */
299
- clinicBranchId: string;
300
- /** Aggregated clinic information (snapshot) */
301
- clinicInfo: ClinicInfo;
302
- /** IANA timezone of the clinic */
303
- clinic_tz: string;
304
-
305
- /** ID of the practitioner */
306
- practitionerId: string;
307
- /** Aggregated practitioner information (snapshot) */
308
- practitionerInfo: PractitionerProfileInfo;
309
-
310
- /** ID of the patient */
311
- patientId: string;
312
- /** Aggregated patient information (snapshot) */
313
- patientInfo: PatientProfileInfo;
314
-
315
- /** ID of the procedure */
316
- procedureId: string;
317
- /** Aggregated procedure information including product/brand (snapshot) */
318
- procedureInfo: ProcedureSummaryInfo; // Aggregated procedure information
319
- /** Extended procedure information */
320
- procedureExtendedInfo: ProcedureExtendedInfo; // Aggregated extended procedure information
321
-
322
- /** Status of the appointment */
323
- status: AppointmentStatus;
324
-
325
- /** Timestamps */
326
- bookingTime: Timestamp;
327
- confirmationTime?: Timestamp | null;
328
- cancellationTime?: Timestamp | null;
329
- rescheduleTime?: Timestamp | null;
330
- /** Reschedule reminder tracking */
331
- rescheduleReminderSentAt?: Timestamp | null;
332
- rescheduleReminderCount?: number;
333
- appointmentStartTime: Timestamp;
334
- appointmentEndTime: Timestamp;
335
- procedureActualStartTime?: Timestamp | null; // NEW: Actual start time of the procedure
336
- actualDurationMinutes?: number;
337
-
338
- /** Cancellation Details */
339
- cancellationReason?: string | null;
340
- canceledBy?: 'patient' | 'clinic' | 'practitioner' | 'system';
341
-
342
- /** Notes */
343
- internalNotes?: string | null;
344
- patientNotes?: string | null;
345
-
346
- /** Payment Details */
347
- cost: number;
348
- currency: Currency;
349
- paymentStatus: PaymentStatus;
350
- paymentTransactionId?: string | null;
351
-
352
- /** Procedure-related conditions and requirements */
353
- blockingConditions: BlockingCondition[];
354
- contraindications: ContraindicationDynamic[];
355
- preProcedureRequirements: Requirement[];
356
- postProcedureRequirements: Requirement[];
357
-
358
- /** Tracking information for requirements completion */
359
- completedPreRequirements?: string[]; // IDs of completed pre-requirements
360
- completedPostRequirements?: string[]; // IDs of completed post-requirements
361
-
362
- /** NEW: Linked forms (consent, procedure-specific forms, etc.) */
363
- linkedFormIds?: string[];
364
- linkedForms?: LinkedFormInfo[];
365
- pendingUserFormsIds?: string[]; // Determines if there are any user forms that are pending for this appointment, blocks the appointment from being checked in (only for user forms with isRequired = true)
366
-
367
- /** NEW: Media items (before/after photos, scanned documents, etc.) */
368
- media?: AppointmentMediaItem[];
369
-
370
- /** NEW: Information about the patient's review for this appointment */
371
- reviewInfo?: PatientReviewInfo | null;
372
-
373
- /** NEW: Details about the finalization of the appointment by the practitioner */
374
- finalizedDetails?: {
375
- by: string; // Practitioner User ID
376
- at: Timestamp;
377
- notes?: string;
378
- };
379
-
380
- /** Timestamps for record creation and updates */
381
- createdAt: Timestamp;
382
- updatedAt: Timestamp;
383
-
384
- /** Recurring appointment information */
385
- isRecurring?: boolean;
386
- recurringAppointmentId?: string | null;
387
-
388
- /** NEW: Flag for soft deletion or archiving */
389
- isArchived?: boolean;
390
-
391
- /** NEW: Metadata for the appointment - used for area selection and photos */
392
- metadata?: AppointmentMetadata;
393
- }
394
-
395
- /**
396
- * Data needed to create a new Appointment
397
- */
398
- export interface CreateAppointmentData {
399
- clinicBranchId: string;
400
- practitionerId: string;
401
- patientId: string;
402
- procedureId: string;
403
- appointmentStartTime: Timestamp;
404
- appointmentEndTime: Timestamp;
405
- cost: number;
406
- currency: Currency;
407
- patientNotes?: string | null;
408
- initialStatus: AppointmentStatus;
409
- initialPaymentStatus?: PaymentStatus; // Defaults to UNPAID if not provided
410
- clinic_tz: string;
411
- }
412
-
413
- /**
414
- * Data needed to create a new Appointment via CreateAppointmentHttp method
415
- */
416
- export interface CreateAppointmentHttpData {
417
- patientId: string;
418
- procedureId: string;
419
- appointmentStartTime: Timestamp;
420
- appointmentEndTime: Timestamp;
421
- patientNotes?: string | null;
422
- }
423
-
424
- /**
425
- * Data allowed for updating an Appointment
426
- */
427
- export interface UpdateAppointmentData {
428
- status?: AppointmentStatus;
429
- confirmationTime?: Timestamp | FieldValue | null;
430
- cancellationTime?: Timestamp | FieldValue | null;
431
- rescheduleTime?: Timestamp | FieldValue | null;
432
- /** Reschedule reminder tracking */
433
- rescheduleReminderSentAt?: Timestamp | FieldValue | null;
434
- rescheduleReminderCount?: number | FieldValue;
435
- procedureActualStartTime?: Timestamp | FieldValue | null; // NEW
436
- actualDurationMinutes?: number;
437
- cancellationReason?: string | null;
438
- canceledBy?: 'patient' | 'clinic' | 'practitioner' | 'system';
439
- internalNotes?: string | null;
440
- patientNotes?: string | FieldValue | null; // Allow FieldValue for deleting
441
- paymentStatus?: PaymentStatus;
442
- paymentTransactionId?: string | FieldValue | null;
443
- completedPreRequirements?: string[] | FieldValue; // Allow FieldValue for arrayUnion/arrayRemove
444
- completedPostRequirements?: string[] | FieldValue;
445
- appointmentStartTime?: Timestamp; // For rescheduling
446
- appointmentEndTime?: Timestamp; // For rescheduling
447
- calendarEventId?: string; // If calendar event needs to be re-linked
448
- cost?: number; // If cost is adjusted
449
- clinicBranchId?: string; // If appointment is moved to another branch (complex scenario)
450
- practitionerId?: string; // If practitioner is changed
451
- clinic_tz?: string;
452
-
453
- /** NEW: For updating linked forms - typically managed by dedicated methods */
454
- linkedFormIds?: string[] | FieldValue;
455
- linkedForms?: LinkedFormInfo[] | FieldValue;
456
-
457
- /** NEW: For updating media items - typically managed by dedicated methods */
458
- media?: AppointmentMediaItem[] | FieldValue;
459
-
460
- /** NEW: For adding/updating review information */
461
- reviewInfo?: PatientReviewInfo | FieldValue | null;
462
-
463
- /** NEW: For setting practitioner finalization details */
464
- finalizedDetails?: { by: string; at: Timestamp; notes?: string } | FieldValue;
465
-
466
- /** NEW: For archiving/unarchiving */
467
- isArchived?: boolean;
468
-
469
- updatedAt?: FieldValue; // To set server timestamp
470
-
471
- /** NEW: For updating metadata */
472
- metadata?: AppointmentMetadata;
473
- }
474
-
475
- /**
476
- * Parameters for searching appointments
477
- */
478
- export interface SearchAppointmentsParams {
479
- patientId?: string;
480
- practitionerId?: string;
481
- clinicBranchId?: string;
482
- startDate?: Date;
483
- endDate?: Date;
484
- status?: AppointmentStatus | AppointmentStatus[];
485
- limit?: number;
486
- startAfter?: any;
487
- }
488
-
489
- /** Firestore collection name */
490
- export const APPOINTMENTS_COLLECTION = 'appointments';
491
-
492
- /**
493
- * Interface for next steps recommendation with context about when and who suggested it
494
- */
495
- export interface NextStepsRecommendation {
496
- /** Unique identifier for this recommendation (appointmentId + recommendationIndex) */
497
- id: string;
498
- /** The recommended procedure details */
499
- recommendedProcedure: RecommendedProcedure;
500
- /** ID of the appointment where this was recommended */
501
- appointmentId: string;
502
- /** Date of the appointment when this was recommended */
503
- appointmentDate: Timestamp;
504
- /** ID of the practitioner who made the recommendation */
505
- practitionerId: string;
506
- /** Name of the practitioner who made the recommendation */
507
- practitionerName: string;
508
- /** ID of the clinic where the appointment took place */
509
- clinicBranchId: string;
510
- /** Name of the clinic where the appointment took place */
511
- clinicName: string;
512
- /** Status of the appointment when recommendation was made */
513
- appointmentStatus: AppointmentStatus;
514
- /** Whether this recommendation has been dismissed by the patient */
515
- isDismissed?: boolean;
516
- /** When the recommendation was dismissed (if dismissed) */
517
- dismissedAt?: Timestamp | null;
1
+ import { Timestamp, FieldValue } from 'firebase/firestore';
2
+ import { ClinicInfo, PractitionerProfileInfo, PatientProfileInfo } from '../profile';
3
+ import { ProcedureSummaryInfo } from '../procedure';
4
+ import { Currency, type PricingMeasure } from '../../backoffice/types/static/pricing.types';
5
+ import { BlockingCondition } from '../../backoffice/types/static/blocking-condition.types';
6
+ import { Requirement } from '../../backoffice/types/requirement.types';
7
+ import { FilledDocumentStatus } from '../documentation-templates';
8
+ import type { ContraindicationDynamic, ProcedureFamily } from '../../backoffice';
9
+ import type { MediaResource } from '../../services/media/media.service';
10
+ import type { ResourceBookingInfo } from '../resource';
11
+ import { string } from 'zod/v4';
12
+
13
+ /**
14
+ * Enum defining the possible statuses of an appointment.
15
+ */
16
+ export enum AppointmentStatus {
17
+ PENDING = 'pending', // Initial state after booking, before confirmation (if applicable)
18
+ CONFIRMED = 'confirmed', // Confirmed by clinic/practitioner
19
+ CHECKED_IN = 'checked_in', // Patient has arrived
20
+ IN_PROGRESS = 'in_progress', // Procedure has started
21
+ COMPLETED = 'completed', // Procedure finished successfully
22
+ CANCELED_PATIENT = 'canceled_patient', // Canceled by the patient
23
+ CANCELED_PATIENT_RESCHEDULED = 'canceled_patient_rescheduled', // Canceled by the patient and rescheduled by the clinic
24
+ CANCELED_CLINIC = 'canceled_clinic', // Canceled by the clinic/practitioner
25
+ NO_SHOW = 'no_show', // Patient did not attend
26
+ RESCHEDULED_BY_CLINIC = 'rescheduled_by_clinic', // When appointment is rescheduled by the clinic, waiting for patient confirmation or cancellation (when reschedule is accepted, status goes to confirmed, if not accepted, then status goes to canceled_patient_rescheduled)
27
+ }
28
+
29
+ /**
30
+ * Enum defining the payment status of an appointment.
31
+ */
32
+ export enum PaymentStatus {
33
+ UNPAID = 'unpaid',
34
+ PAID = 'paid',
35
+ PARTIALLY_PAID = 'partially_paid',
36
+ REFUNDED = 'refunded',
37
+ NOT_APPLICABLE = 'not_applicable', // For free services or other scenarios
38
+ }
39
+
40
+ /**
41
+ * Enum for different types of media that can be attached to an appointment.
42
+ */
43
+ export enum MediaType {
44
+ BEFORE_PHOTO = 'before_photo',
45
+ AFTER_PHOTO = 'after_photo',
46
+ CONSENT_SCAN = 'consent_scan',
47
+ OTHER_DOCUMENT = 'other_document',
48
+ }
49
+
50
+ /**
51
+ * Interface to describe a media file linked to an appointment.
52
+ */
53
+ export interface AppointmentMediaItem {
54
+ id: string; // Auto-generated unique ID for the media item
55
+ type: MediaType;
56
+ url: string; // Cloud Storage URL
57
+ fileName?: string;
58
+ uploadedAt: Timestamp;
59
+ uploadedBy: string; // User ID (patient, practitioner, or clinic_admin)
60
+ description?: string;
61
+ }
62
+
63
+ /**
64
+ * Interface for procedure-specific information
65
+ */
66
+ export interface ProcedureExtendedInfo {
67
+ id: string;
68
+ name: string;
69
+ description: string;
70
+ cost: number;
71
+ duration: number;
72
+ procedureFamily: ProcedureFamily;
73
+ procedureCategoryId: string;
74
+ procedureCategoryName: string;
75
+ procedureSubCategoryId: string;
76
+ procedureSubCategoryName: string;
77
+ procedureTechnologyId: string;
78
+ procedureTechnologyName: string;
79
+ procedureProductBrandId: string;
80
+ procedureProductBrandName: string;
81
+ procedureProducts: Array<{
82
+ productId: string;
83
+ productName: string;
84
+ brandId: string;
85
+ brandName: string;
86
+ }>;
87
+ }
88
+
89
+ /**
90
+ * Interface to describe a filled form linked to an appointment.
91
+ */
92
+ export interface LinkedFormInfo {
93
+ formId: string; // ID of the FilledDocument
94
+ templateId: string;
95
+ templateVersion: number;
96
+ title: string; // For display, usually from DocumentTemplate.title
97
+ isUserForm: boolean;
98
+ isRequired?: boolean;
99
+ sortingOrder?: number;
100
+ status: FilledDocumentStatus; // Status of the filled form (e.g., draft, completed, signed)
101
+ path: string; // Full Firestore path to the filled document (e.g., appointments/{aid}/user-forms/{fid})
102
+ submittedAt?: Timestamp;
103
+ completedAt?: Timestamp; // When the form reached a final state like 'completed' or 'signed'
104
+ procedureId?: string; // ID of the procedure this form belongs to (for extended procedure forms)
105
+ }
106
+
107
+ /**
108
+ * Interface for summarized patient review information linked to an appointment.
109
+ */
110
+ export interface PatientReviewInfo {
111
+ reviewId: string; // ID of the full review document/record if stored elsewhere
112
+ rating: number; // e.g., 1-5 stars
113
+ comment?: string; // A short snippet or the full comment
114
+ reviewedAt: Timestamp;
115
+ }
116
+
117
+ /**
118
+ * Interface for before/after photos and notes per zone
119
+ */
120
+ export interface BeforeAfterPerZone {
121
+ /** URL for before photo or null if not available */
122
+ before: MediaResource | null;
123
+ /** URL for after photo or null if not available */
124
+ after: MediaResource | null;
125
+ /** Optional note for the before photo */
126
+ beforeNote?: string | null;
127
+ /** Optional note for the after photo */
128
+ afterNote?: string | null;
129
+ /** Whether this photo pair (before AND after) should be visible to the patient */
130
+ showToPatient?: boolean;
131
+ /** Whether the before note should be visible to the patient */
132
+ beforeNoteVisibleToPatient?: boolean;
133
+ /** Whether the after note should be visible to the patient */
134
+ afterNoteVisibleToPatient?: boolean;
135
+ /** Timestamp when visibility was last updated */
136
+ visibilityUpdatedAt?: Timestamp;
137
+ /** ID of the doctor who last updated visibility */
138
+ visibilityUpdatedBy?: string;
139
+ }
140
+
141
+ /**
142
+ * Interface for zone photo upload data
143
+ */
144
+ export interface ZonePhotoUploadData {
145
+ appointmentId: string;
146
+ zoneId: string;
147
+ photoType: 'before' | 'after';
148
+ file: File | Blob;
149
+ notes?: string;
150
+ }
151
+
152
+ /**
153
+ * Interface for zone item data (products or notes per zone)
154
+ */
155
+ export interface ZoneItemData {
156
+ productId?: string;
157
+ productName?: string;
158
+ productBrandId?: string;
159
+ productBrandName?: string;
160
+ belongingProcedureId: string;
161
+ type: 'item' | 'note';
162
+ stage?: 'before' | 'after'; // Stage of the note/item: 'before' for planning notes, 'after' for treatment notes
163
+ price?: number;
164
+ currency?: Currency;
165
+ unitOfMeasurement?: PricingMeasure;
166
+ priceOverrideAmount?: number; // If set, takes precedence over price
167
+ quantity?: number;
168
+ parentZone: string; // Zone key in format "category.zone" (e.g., "face.forehead")
169
+ subzones: string[];
170
+ notes?: string;
171
+ notesVisibleToPatient?: boolean; // Whether notes are visible to patient (privacy-first, default false)
172
+ subtotal?: number;
173
+ ionNumber?: string | null; // Batch/Lot number - can be null to clear/delete
174
+ expiryDate?: string | null; // ISO date string (YYYY-MM-DD) - can be null to clear/delete
175
+ createdAt?: string; // ISO timestamp
176
+ updatedAt?: string; // ISO timestamp
177
+ }
178
+
179
+ /**
180
+ * @deprecated Use ZoneItemData instead
181
+ */
182
+ export interface BillingPerZone {
183
+ Product: string;
184
+ ProductId: string | null;
185
+ Quantity: number;
186
+ UnitOfMeasurement: PricingMeasure;
187
+ UnitPrice: number;
188
+ UnitCurency: Currency;
189
+ Subtotal: number;
190
+ Note: string | null;
191
+ IonNumber: string | null;
192
+ }
193
+
194
+ /**
195
+ * Interface for final billing calculations of the appointment
196
+ */
197
+ export interface FinalBilling {
198
+ /** Total of all subtotals from all zones */
199
+ subtotalAll: number;
200
+ /** Overall discount applied to the subtotal */
201
+ discount?: {
202
+ type: 'percentage' | 'fixed';
203
+ value: number; // e.g., 10 for 10% or 50 for CHF 50
204
+ amount: number; // calculated discount in currency
205
+ };
206
+ /** Subtotal after discount (subtotalAll - discount.amount) */
207
+ discountedSubtotal?: number;
208
+ /** Tax rate as percentage (e.g., 0.20 for 20%) */
209
+ taxRate: number;
210
+ /** Calculated tax amount */
211
+ taxPrice: number;
212
+ /** Final price including tax */
213
+ finalPrice: number;
214
+ /** Currency for the final billing */
215
+ currency: Currency;
216
+ }
217
+
218
+ /**
219
+ * Interface for product metadata in appointment
220
+ */
221
+ export interface AppointmentProductMetadata {
222
+ productId: string;
223
+ productName: string;
224
+ brandId: string;
225
+ brandName: string;
226
+ procedureId: string;
227
+ price: number;
228
+ currency: Currency;
229
+ unitOfMeasurement: PricingMeasure;
230
+ }
231
+
232
+ /**
233
+ * Interface for extended procedures in appointment
234
+ */
235
+ export interface ExtendedProcedureInfo {
236
+ procedureId: string;
237
+ procedureName: string;
238
+ procedureDescription?: string;
239
+ procedurePrice?: number;
240
+ procedureFamily?: ProcedureFamily;
241
+ procedureCategoryId: string;
242
+ procedureCategoryName: string;
243
+ procedureSubCategoryId: string;
244
+ procedureSubCategoryName: string;
245
+ procedureTechnologyId: string;
246
+ procedureTechnologyName: string;
247
+ procedureProducts: Array<{
248
+ productId: string;
249
+ productName: string;
250
+ brandId: string;
251
+ brandName: string;
252
+ }>;
253
+ }
254
+
255
+ export interface RecommendedProcedure {
256
+ procedure: ExtendedProcedureInfo;
257
+ note: string;
258
+ timeframe: {
259
+ value: number;
260
+ unit: 'day' | 'week' | 'month' | 'year';
261
+ };
262
+ }
263
+
264
+ /**
265
+ * Interface for appointment metadata containing zone-specific information
266
+ */
267
+ export interface AppointmentMetadata {
268
+ selectedZones: string[] | null;
269
+ zonePhotos: Record<string, BeforeAfterPerZone[]> | null;
270
+ zonesData?: Record<string, ZoneItemData[]> | null;
271
+ appointmentProducts?: AppointmentProductMetadata[];
272
+ extendedProcedures?: ExtendedProcedureInfo[];
273
+ recommendedProcedures: RecommendedProcedure[]
274
+ finalbilling: FinalBilling | null;
275
+ /** Final treatment notes shared with patient */
276
+ finalizationNotesShared?: string | null;
277
+ /** Final treatment notes for internal use only (not shared with patient) */
278
+ finalizationNotesInternal?: string | null;
279
+ /**
280
+ * @deprecated Use finalizationNotesShared instead. Kept for backward compatibility during migration.
281
+ */
282
+ finalizationNotes?: string | null;
283
+
284
+ /**
285
+ * @deprecated Use zonesData instead
286
+ */
287
+ zoneBilling?: Record<string, BillingPerZone> | null;
288
+ }
289
+
290
+ /**
291
+ * Represents a booked appointment, aggregating key information and relevant procedure rules.
292
+ */
293
+ export interface Appointment {
294
+ /** Unique identifier for the appointment */
295
+ id: string;
296
+ /** Reference to the associated CalendarEvent */
297
+ calendarEventId: string;
298
+
299
+ /** ID of the clinic branch */
300
+ clinicBranchId: string;
301
+ /** Aggregated clinic information (snapshot) */
302
+ clinicInfo: ClinicInfo;
303
+ /** IANA timezone of the clinic */
304
+ clinic_tz: string;
305
+
306
+ /** ID of the practitioner */
307
+ practitionerId: string;
308
+ /** Aggregated practitioner information (snapshot) */
309
+ practitionerInfo: PractitionerProfileInfo;
310
+
311
+ /** ID of the patient */
312
+ patientId: string;
313
+ /** Aggregated patient information (snapshot) */
314
+ patientInfo: PatientProfileInfo;
315
+
316
+ /** ID of the procedure */
317
+ procedureId: string;
318
+ /** Aggregated procedure information including product/brand (snapshot) */
319
+ procedureInfo: ProcedureSummaryInfo; // Aggregated procedure information
320
+ /** Extended procedure information */
321
+ procedureExtendedInfo: ProcedureExtendedInfo; // Aggregated extended procedure information
322
+
323
+ /** Status of the appointment */
324
+ status: AppointmentStatus;
325
+
326
+ /** Timestamps */
327
+ bookingTime: Timestamp;
328
+ confirmationTime?: Timestamp | null;
329
+ cancellationTime?: Timestamp | null;
330
+ rescheduleTime?: Timestamp | null;
331
+ /** Reschedule reminder tracking */
332
+ rescheduleReminderSentAt?: Timestamp | null;
333
+ rescheduleReminderCount?: number;
334
+ appointmentStartTime: Timestamp;
335
+ appointmentEndTime: Timestamp;
336
+ procedureActualStartTime?: Timestamp | null; // NEW: Actual start time of the procedure
337
+ actualDurationMinutes?: number;
338
+
339
+ /** Cancellation Details */
340
+ cancellationReason?: string | null;
341
+ canceledBy?: 'patient' | 'clinic' | 'practitioner' | 'system';
342
+
343
+ /** Notes */
344
+ internalNotes?: string | null;
345
+ patientNotes?: string | null;
346
+
347
+ /** Payment Details */
348
+ cost: number;
349
+ currency: Currency;
350
+ paymentStatus: PaymentStatus;
351
+ paymentTransactionId?: string | null;
352
+
353
+ /** Procedure-related conditions and requirements */
354
+ blockingConditions: BlockingCondition[];
355
+ contraindications: ContraindicationDynamic[];
356
+ preProcedureRequirements: Requirement[];
357
+ postProcedureRequirements: Requirement[];
358
+
359
+ /** Tracking information for requirements completion */
360
+ completedPreRequirements?: string[]; // IDs of completed pre-requirements
361
+ completedPostRequirements?: string[]; // IDs of completed post-requirements
362
+
363
+ /** NEW: Linked forms (consent, procedure-specific forms, etc.) */
364
+ linkedFormIds?: string[];
365
+ linkedForms?: LinkedFormInfo[];
366
+ pendingUserFormsIds?: string[]; // Determines if there are any user forms that are pending for this appointment, blocks the appointment from being checked in (only for user forms with isRequired = true)
367
+
368
+ /** NEW: Media items (before/after photos, scanned documents, etc.) */
369
+ media?: AppointmentMediaItem[];
370
+
371
+ /** NEW: Information about the patient's review for this appointment */
372
+ reviewInfo?: PatientReviewInfo | null;
373
+
374
+ /** NEW: Details about the finalization of the appointment by the practitioner */
375
+ finalizedDetails?: {
376
+ by: string; // Practitioner User ID
377
+ at: Timestamp;
378
+ notes?: string;
379
+ };
380
+
381
+ /** Timestamps for record creation and updates */
382
+ createdAt: Timestamp;
383
+ updatedAt: Timestamp;
384
+
385
+ /** Recurring appointment information */
386
+ isRecurring?: boolean;
387
+ recurringAppointmentId?: string | null;
388
+
389
+ /** NEW: Flag for soft deletion or archiving */
390
+ isArchived?: boolean;
391
+
392
+ /** NEW: Metadata for the appointment - used for area selection and photos */
393
+ metadata?: AppointmentMetadata;
394
+
395
+ /** Resources booked for this appointment (e.g., surgery room instance, device instance) */
396
+ resourceBookings?: ResourceBookingInfo[];
397
+ }
398
+
399
+ /**
400
+ * Data needed to create a new Appointment
401
+ */
402
+ export interface CreateAppointmentData {
403
+ clinicBranchId: string;
404
+ practitionerId: string;
405
+ patientId: string;
406
+ procedureId: string;
407
+ appointmentStartTime: Timestamp;
408
+ appointmentEndTime: Timestamp;
409
+ cost: number;
410
+ currency: Currency;
411
+ patientNotes?: string | null;
412
+ initialStatus: AppointmentStatus;
413
+ initialPaymentStatus?: PaymentStatus; // Defaults to UNPAID if not provided
414
+ clinic_tz: string;
415
+ }
416
+
417
+ /**
418
+ * Data needed to create a new Appointment via CreateAppointmentHttp method
419
+ */
420
+ export interface CreateAppointmentHttpData {
421
+ patientId: string;
422
+ procedureId: string;
423
+ appointmentStartTime: Timestamp;
424
+ appointmentEndTime: Timestamp;
425
+ patientNotes?: string | null;
426
+ }
427
+
428
+ /**
429
+ * Data allowed for updating an Appointment
430
+ */
431
+ export interface UpdateAppointmentData {
432
+ status?: AppointmentStatus;
433
+ confirmationTime?: Timestamp | FieldValue | null;
434
+ cancellationTime?: Timestamp | FieldValue | null;
435
+ rescheduleTime?: Timestamp | FieldValue | null;
436
+ /** Reschedule reminder tracking */
437
+ rescheduleReminderSentAt?: Timestamp | FieldValue | null;
438
+ rescheduleReminderCount?: number | FieldValue;
439
+ procedureActualStartTime?: Timestamp | FieldValue | null; // NEW
440
+ actualDurationMinutes?: number;
441
+ cancellationReason?: string | null;
442
+ canceledBy?: 'patient' | 'clinic' | 'practitioner' | 'system';
443
+ internalNotes?: string | null;
444
+ patientNotes?: string | FieldValue | null; // Allow FieldValue for deleting
445
+ paymentStatus?: PaymentStatus;
446
+ paymentTransactionId?: string | FieldValue | null;
447
+ completedPreRequirements?: string[] | FieldValue; // Allow FieldValue for arrayUnion/arrayRemove
448
+ completedPostRequirements?: string[] | FieldValue;
449
+ appointmentStartTime?: Timestamp; // For rescheduling
450
+ appointmentEndTime?: Timestamp; // For rescheduling
451
+ calendarEventId?: string; // If calendar event needs to be re-linked
452
+ cost?: number; // If cost is adjusted
453
+ clinicBranchId?: string; // If appointment is moved to another branch (complex scenario)
454
+ practitionerId?: string; // If practitioner is changed
455
+ clinic_tz?: string;
456
+
457
+ /** NEW: For updating linked forms - typically managed by dedicated methods */
458
+ linkedFormIds?: string[] | FieldValue;
459
+ linkedForms?: LinkedFormInfo[] | FieldValue;
460
+
461
+ /** NEW: For updating media items - typically managed by dedicated methods */
462
+ media?: AppointmentMediaItem[] | FieldValue;
463
+
464
+ /** NEW: For adding/updating review information */
465
+ reviewInfo?: PatientReviewInfo | FieldValue | null;
466
+
467
+ /** NEW: For setting practitioner finalization details */
468
+ finalizedDetails?: { by: string; at: Timestamp; notes?: string } | FieldValue;
469
+
470
+ /** NEW: For archiving/unarchiving */
471
+ isArchived?: boolean;
472
+
473
+ updatedAt?: FieldValue; // To set server timestamp
474
+
475
+ /** NEW: For updating metadata */
476
+ metadata?: AppointmentMetadata;
477
+
478
+ /** For updating resource bookings */
479
+ resourceBookings?: ResourceBookingInfo[] | FieldValue;
480
+ }
481
+
482
+ /**
483
+ * Parameters for searching appointments
484
+ */
485
+ export interface SearchAppointmentsParams {
486
+ patientId?: string;
487
+ practitionerId?: string;
488
+ clinicBranchId?: string;
489
+ startDate?: Date;
490
+ endDate?: Date;
491
+ status?: AppointmentStatus | AppointmentStatus[];
492
+ limit?: number;
493
+ startAfter?: any;
494
+ }
495
+
496
+ /** Firestore collection name */
497
+ export const APPOINTMENTS_COLLECTION = 'appointments';
498
+
499
+ /**
500
+ * Interface for next steps recommendation with context about when and who suggested it
501
+ */
502
+ export interface NextStepsRecommendation {
503
+ /** Unique identifier for this recommendation (appointmentId + recommendationIndex) */
504
+ id: string;
505
+ /** The recommended procedure details */
506
+ recommendedProcedure: RecommendedProcedure;
507
+ /** ID of the appointment where this was recommended */
508
+ appointmentId: string;
509
+ /** Date of the appointment when this was recommended */
510
+ appointmentDate: Timestamp;
511
+ /** ID of the practitioner who made the recommendation */
512
+ practitionerId: string;
513
+ /** Name of the practitioner who made the recommendation */
514
+ practitionerName: string;
515
+ /** ID of the clinic where the appointment took place */
516
+ clinicBranchId: string;
517
+ /** Name of the clinic where the appointment took place */
518
+ clinicName: string;
519
+ /** Status of the appointment when recommendation was made */
520
+ appointmentStatus: AppointmentStatus;
521
+ /** Whether this recommendation has been dismissed by the patient */
522
+ isDismissed?: boolean;
523
+ /** When the recommendation was dismissed (if dismissed) */
524
+ dismissedAt?: Timestamp | null;
518
525
  }