@blackcode_sa/metaestetics-api 1.13.5 → 1.13.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (295) hide show
  1. package/dist/admin/index.d.mts +20 -1
  2. package/dist/admin/index.d.ts +20 -1
  3. package/dist/admin/index.js +217 -1
  4. package/dist/admin/index.mjs +217 -1
  5. package/dist/index.d.mts +26 -3
  6. package/dist/index.d.ts +26 -3
  7. package/dist/index.js +168 -6
  8. package/dist/index.mjs +168 -6
  9. package/package.json +121 -121
  10. package/src/__mocks__/firstore.ts +10 -10
  11. package/src/admin/aggregation/README.md +79 -79
  12. package/src/admin/aggregation/appointment/README.md +128 -128
  13. package/src/admin/aggregation/appointment/appointment.aggregation.service.ts +1984 -1984
  14. package/src/admin/aggregation/appointment/index.ts +1 -1
  15. package/src/admin/aggregation/clinic/README.md +52 -52
  16. package/src/admin/aggregation/clinic/clinic.aggregation.service.ts +966 -703
  17. package/src/admin/aggregation/clinic/index.ts +1 -1
  18. package/src/admin/aggregation/forms/README.md +13 -13
  19. package/src/admin/aggregation/forms/filled-forms.aggregation.service.ts +322 -322
  20. package/src/admin/aggregation/forms/index.ts +1 -1
  21. package/src/admin/aggregation/index.ts +8 -8
  22. package/src/admin/aggregation/patient/README.md +27 -27
  23. package/src/admin/aggregation/patient/index.ts +1 -1
  24. package/src/admin/aggregation/patient/patient.aggregation.service.ts +141 -141
  25. package/src/admin/aggregation/practitioner/README.md +42 -42
  26. package/src/admin/aggregation/practitioner/index.ts +1 -1
  27. package/src/admin/aggregation/practitioner/practitioner.aggregation.service.ts +433 -433
  28. package/src/admin/aggregation/practitioner-invite/index.ts +1 -1
  29. package/src/admin/aggregation/practitioner-invite/practitioner-invite.aggregation.service.ts +961 -961
  30. package/src/admin/aggregation/procedure/README.md +43 -43
  31. package/src/admin/aggregation/procedure/index.ts +1 -1
  32. package/src/admin/aggregation/procedure/procedure.aggregation.service.ts +702 -702
  33. package/src/admin/aggregation/reviews/index.ts +1 -1
  34. package/src/admin/aggregation/reviews/reviews.aggregation.service.ts +689 -689
  35. package/src/admin/analytics/analytics.admin.service.ts +278 -278
  36. package/src/admin/analytics/index.ts +2 -2
  37. package/src/admin/booking/README.md +125 -125
  38. package/src/admin/booking/booking.admin.ts +1037 -1037
  39. package/src/admin/booking/booking.calculator.ts +712 -712
  40. package/src/admin/booking/booking.types.ts +59 -59
  41. package/src/admin/booking/index.ts +3 -3
  42. package/src/admin/booking/timezones-problem.md +185 -185
  43. package/src/admin/calendar/README.md +7 -7
  44. package/src/admin/calendar/calendar.admin.service.ts +345 -345
  45. package/src/admin/calendar/index.ts +1 -1
  46. package/src/admin/documentation-templates/document-manager.admin.ts +260 -260
  47. package/src/admin/documentation-templates/index.ts +1 -1
  48. package/src/admin/free-consultation/free-consultation-utils.admin.ts +148 -148
  49. package/src/admin/free-consultation/index.ts +1 -1
  50. package/src/admin/index.ts +81 -81
  51. package/src/admin/logger/index.ts +78 -78
  52. package/src/admin/mailing/README.md +95 -95
  53. package/src/admin/mailing/appointment/appointment.mailing.service.ts +732 -732
  54. package/src/admin/mailing/appointment/index.ts +1 -1
  55. package/src/admin/mailing/appointment/templates/patient/appointment-confirmed.html +40 -40
  56. package/src/admin/mailing/base.mailing.service.ts +208 -208
  57. package/src/admin/mailing/index.ts +3 -3
  58. package/src/admin/mailing/practitionerInvite/existing-practitioner-invite.mailing.ts +611 -611
  59. package/src/admin/mailing/practitionerInvite/index.ts +2 -2
  60. package/src/admin/mailing/practitionerInvite/practitionerInvite.mailing.ts +395 -395
  61. package/src/admin/mailing/practitionerInvite/templates/existing-practitioner-invitation.template.ts +155 -155
  62. package/src/admin/mailing/practitionerInvite/templates/invitation.template.ts +101 -101
  63. package/src/admin/mailing/practitionerInvite/templates/invite-accepted-notification.template.ts +228 -228
  64. package/src/admin/mailing/practitionerInvite/templates/invite-rejected-notification.template.ts +242 -242
  65. package/src/admin/notifications/index.ts +1 -1
  66. package/src/admin/notifications/notifications.admin.ts +710 -710
  67. package/src/admin/requirements/README.md +128 -128
  68. package/src/admin/requirements/index.ts +1 -1
  69. package/src/admin/requirements/patient-requirements.admin.service.ts +475 -475
  70. package/src/admin/users/index.ts +1 -1
  71. package/src/admin/users/user-profile.admin.ts +405 -405
  72. package/src/backoffice/constants/certification.constants.ts +13 -13
  73. package/src/backoffice/constants/index.ts +1 -1
  74. package/src/backoffice/errors/backoffice.errors.ts +181 -181
  75. package/src/backoffice/errors/index.ts +1 -1
  76. package/src/backoffice/expo-safe/README.md +26 -26
  77. package/src/backoffice/expo-safe/index.ts +41 -41
  78. package/src/backoffice/index.ts +5 -5
  79. package/src/backoffice/services/FIXES_README.md +102 -102
  80. package/src/backoffice/services/README.md +57 -57
  81. package/src/backoffice/services/analytics.service.proposal.md +863 -863
  82. package/src/backoffice/services/analytics.service.summary.md +143 -143
  83. package/src/backoffice/services/brand.service.ts +256 -256
  84. package/src/backoffice/services/category.service.ts +384 -384
  85. package/src/backoffice/services/constants.service.ts +385 -385
  86. package/src/backoffice/services/documentation-template.service.ts +202 -202
  87. package/src/backoffice/services/index.ts +10 -10
  88. package/src/backoffice/services/migrate-products.ts +116 -116
  89. package/src/backoffice/services/product.service.ts +553 -553
  90. package/src/backoffice/services/requirement.service.ts +235 -235
  91. package/src/backoffice/services/subcategory.service.ts +461 -461
  92. package/src/backoffice/services/technology.service.ts +1151 -1151
  93. package/src/backoffice/types/README.md +12 -12
  94. package/src/backoffice/types/admin-constants.types.ts +69 -69
  95. package/src/backoffice/types/brand.types.ts +29 -29
  96. package/src/backoffice/types/category.types.ts +67 -67
  97. package/src/backoffice/types/documentation-templates.types.ts +28 -28
  98. package/src/backoffice/types/index.ts +10 -10
  99. package/src/backoffice/types/procedure-product.types.ts +38 -38
  100. package/src/backoffice/types/product.types.ts +240 -240
  101. package/src/backoffice/types/requirement.types.ts +63 -63
  102. package/src/backoffice/types/static/README.md +18 -18
  103. package/src/backoffice/types/static/blocking-condition.types.ts +21 -21
  104. package/src/backoffice/types/static/certification.types.ts +37 -37
  105. package/src/backoffice/types/static/contraindication.types.ts +19 -19
  106. package/src/backoffice/types/static/index.ts +6 -6
  107. package/src/backoffice/types/static/pricing.types.ts +16 -16
  108. package/src/backoffice/types/static/procedure-family.types.ts +14 -14
  109. package/src/backoffice/types/static/treatment-benefit.types.ts +22 -22
  110. package/src/backoffice/types/subcategory.types.ts +34 -34
  111. package/src/backoffice/types/technology.types.ts +168 -168
  112. package/src/backoffice/validations/index.ts +1 -1
  113. package/src/backoffice/validations/schemas.ts +164 -164
  114. package/src/config/__mocks__/firebase.ts +99 -99
  115. package/src/config/firebase.ts +78 -78
  116. package/src/config/index.ts +9 -9
  117. package/src/errors/auth.error.ts +6 -6
  118. package/src/errors/auth.errors.ts +211 -200
  119. package/src/errors/clinic.errors.ts +32 -32
  120. package/src/errors/firebase.errors.ts +47 -47
  121. package/src/errors/user.errors.ts +99 -99
  122. package/src/index.backup.ts +407 -407
  123. package/src/index.ts +6 -6
  124. package/src/locales/en.ts +31 -31
  125. package/src/recommender/admin/index.ts +1 -1
  126. package/src/recommender/admin/services/recommender.service.admin.ts +5 -5
  127. package/src/recommender/front/index.ts +1 -1
  128. package/src/recommender/front/services/onboarding.service.ts +5 -5
  129. package/src/recommender/front/services/recommender.service.ts +3 -3
  130. package/src/recommender/index.ts +1 -1
  131. package/src/services/PATIENTAUTH.MD +197 -197
  132. package/src/services/README.md +106 -106
  133. package/src/services/__tests__/auth/auth.mock.test.ts +17 -17
  134. package/src/services/__tests__/auth/auth.setup.ts +293 -293
  135. package/src/services/__tests__/auth.service.test.ts +346 -346
  136. package/src/services/__tests__/base.service.test.ts +77 -77
  137. package/src/services/__tests__/user.service.test.ts +528 -528
  138. package/src/services/analytics/ARCHITECTURE.md +199 -199
  139. package/src/services/analytics/CLOUD_FUNCTIONS.md +225 -225
  140. package/src/services/analytics/GROUPED_ANALYTICS.md +501 -501
  141. package/src/services/analytics/QUICK_START.md +393 -393
  142. package/src/services/analytics/README.md +304 -304
  143. package/src/services/analytics/SUMMARY.md +141 -141
  144. package/src/services/analytics/TRENDS.md +380 -380
  145. package/src/services/analytics/USAGE_GUIDE.md +518 -518
  146. package/src/services/analytics/analytics-cloud.service.ts +222 -222
  147. package/src/services/analytics/analytics.service.ts +2142 -2142
  148. package/src/services/analytics/index.ts +4 -4
  149. package/src/services/analytics/review-analytics.service.ts +941 -941
  150. package/src/services/analytics/utils/appointment-filtering.utils.ts +138 -138
  151. package/src/services/analytics/utils/cost-calculation.utils.ts +182 -182
  152. package/src/services/analytics/utils/grouping.utils.ts +434 -434
  153. package/src/services/analytics/utils/stored-analytics.utils.ts +347 -347
  154. package/src/services/analytics/utils/time-calculation.utils.ts +186 -186
  155. package/src/services/analytics/utils/trend-calculation.utils.ts +200 -200
  156. package/src/services/appointment/README.md +17 -17
  157. package/src/services/appointment/appointment.service.ts +2558 -2558
  158. package/src/services/appointment/index.ts +1 -1
  159. package/src/services/appointment/utils/appointment.utils.ts +552 -552
  160. package/src/services/appointment/utils/extended-procedure.utils.ts +314 -314
  161. package/src/services/appointment/utils/form-initialization.utils.ts +225 -225
  162. package/src/services/appointment/utils/recommended-procedure.utils.ts +195 -195
  163. package/src/services/appointment/utils/zone-management.utils.ts +353 -353
  164. package/src/services/appointment/utils/zone-photo.utils.ts +152 -152
  165. package/src/services/auth/auth.service.ts +1043 -989
  166. package/src/services/auth/auth.v2.service.ts +961 -961
  167. package/src/services/auth/index.ts +7 -7
  168. package/src/services/auth/utils/error.utils.ts +90 -90
  169. package/src/services/auth/utils/firebase.utils.ts +49 -49
  170. package/src/services/auth/utils/index.ts +21 -21
  171. package/src/services/auth/utils/practitioner.utils.ts +125 -125
  172. package/src/services/base.service.ts +41 -41
  173. package/src/services/calendar/calendar.service.ts +1077 -1077
  174. package/src/services/calendar/calendar.v2.service.ts +1683 -1683
  175. package/src/services/calendar/calendar.v3.service.ts +313 -313
  176. package/src/services/calendar/externalCalendar.service.ts +178 -178
  177. package/src/services/calendar/index.ts +5 -5
  178. package/src/services/calendar/synced-calendars.service.ts +743 -743
  179. package/src/services/calendar/utils/appointment.utils.ts +265 -265
  180. package/src/services/calendar/utils/calendar-event.utils.ts +646 -646
  181. package/src/services/calendar/utils/clinic.utils.ts +237 -237
  182. package/src/services/calendar/utils/docs.utils.ts +157 -157
  183. package/src/services/calendar/utils/google-calendar.utils.ts +697 -697
  184. package/src/services/calendar/utils/index.ts +8 -8
  185. package/src/services/calendar/utils/patient.utils.ts +198 -198
  186. package/src/services/calendar/utils/practitioner.utils.ts +221 -221
  187. package/src/services/calendar/utils/synced-calendar.utils.ts +472 -472
  188. package/src/services/clinic/README.md +204 -204
  189. package/src/services/clinic/__tests__/clinic-admin.service.test.ts +287 -287
  190. package/src/services/clinic/__tests__/clinic-group.service.test.ts +352 -352
  191. package/src/services/clinic/__tests__/clinic.service.test.ts +354 -354
  192. package/src/services/clinic/billing-transactions.service.ts +217 -217
  193. package/src/services/clinic/clinic-admin.service.ts +202 -202
  194. package/src/services/clinic/clinic-group.service.ts +310 -310
  195. package/src/services/clinic/clinic.service.ts +708 -708
  196. package/src/services/clinic/index.ts +5 -5
  197. package/src/services/clinic/practitioner-invite.service.ts +519 -519
  198. package/src/services/clinic/utils/admin.utils.ts +551 -551
  199. package/src/services/clinic/utils/clinic-group.utils.ts +646 -646
  200. package/src/services/clinic/utils/clinic.utils.ts +949 -949
  201. package/src/services/clinic/utils/filter.utils.d.ts +23 -23
  202. package/src/services/clinic/utils/filter.utils.ts +446 -446
  203. package/src/services/clinic/utils/index.ts +11 -11
  204. package/src/services/clinic/utils/photos.utils.ts +188 -188
  205. package/src/services/clinic/utils/search.utils.ts +84 -84
  206. package/src/services/clinic/utils/tag.utils.ts +124 -124
  207. package/src/services/documentation-templates/documentation-template.service.ts +537 -537
  208. package/src/services/documentation-templates/filled-document.service.ts +587 -587
  209. package/src/services/documentation-templates/index.ts +2 -2
  210. package/src/services/index.ts +14 -14
  211. package/src/services/media/index.ts +1 -1
  212. package/src/services/media/media.service.ts +418 -418
  213. package/src/services/notifications/__tests__/notification.service.test.ts +242 -242
  214. package/src/services/notifications/index.ts +1 -1
  215. package/src/services/notifications/notification.service.ts +215 -215
  216. package/src/services/patient/README.md +48 -48
  217. package/src/services/patient/To-Do.md +43 -43
  218. package/src/services/patient/__tests__/patient.service.test.ts +294 -294
  219. package/src/services/patient/index.ts +2 -2
  220. package/src/services/patient/patient.service.ts +883 -883
  221. package/src/services/patient/patientRequirements.service.ts +285 -285
  222. package/src/services/patient/utils/aesthetic-analysis.utils.ts +176 -176
  223. package/src/services/patient/utils/clinic.utils.ts +80 -80
  224. package/src/services/patient/utils/docs.utils.ts +142 -142
  225. package/src/services/patient/utils/index.ts +9 -9
  226. package/src/services/patient/utils/location.utils.ts +126 -126
  227. package/src/services/patient/utils/medical-stuff.utils.ts +143 -143
  228. package/src/services/patient/utils/medical.utils.ts +458 -458
  229. package/src/services/patient/utils/practitioner.utils.ts +260 -260
  230. package/src/services/patient/utils/profile.utils.ts +510 -510
  231. package/src/services/patient/utils/sensitive.utils.ts +260 -260
  232. package/src/services/patient/utils/token.utils.ts +211 -211
  233. package/src/services/practitioner/README.md +145 -145
  234. package/src/services/practitioner/index.ts +1 -1
  235. package/src/services/practitioner/practitioner.service.ts +1799 -1742
  236. package/src/services/procedure/README.md +163 -163
  237. package/src/services/procedure/index.ts +1 -1
  238. package/src/services/procedure/procedure.service.ts +2307 -2200
  239. package/src/services/reviews/index.ts +1 -1
  240. package/src/services/reviews/reviews.service.ts +734 -734
  241. package/src/services/user/index.ts +1 -1
  242. package/src/services/user/user.service.ts +489 -489
  243. package/src/services/user/user.v2.service.ts +466 -466
  244. package/src/types/analytics/analytics.types.ts +597 -597
  245. package/src/types/analytics/grouped-analytics.types.ts +173 -173
  246. package/src/types/analytics/index.ts +4 -4
  247. package/src/types/analytics/stored-analytics.types.ts +137 -137
  248. package/src/types/appointment/index.ts +480 -480
  249. package/src/types/calendar/index.ts +258 -258
  250. package/src/types/calendar/synced-calendar.types.ts +66 -66
  251. package/src/types/clinic/index.ts +498 -498
  252. package/src/types/clinic/practitioner-invite.types.ts +91 -91
  253. package/src/types/clinic/preferences.types.ts +159 -159
  254. package/src/types/clinic/to-do +3 -3
  255. package/src/types/documentation-templates/index.ts +308 -308
  256. package/src/types/index.ts +47 -47
  257. package/src/types/notifications/README.md +77 -77
  258. package/src/types/notifications/index.ts +286 -286
  259. package/src/types/patient/aesthetic-analysis.types.ts +66 -66
  260. package/src/types/patient/allergies.ts +58 -58
  261. package/src/types/patient/index.ts +275 -275
  262. package/src/types/patient/medical-info.types.ts +152 -152
  263. package/src/types/patient/patient-requirements.ts +92 -92
  264. package/src/types/patient/token.types.ts +61 -61
  265. package/src/types/practitioner/index.ts +206 -206
  266. package/src/types/procedure/index.ts +181 -181
  267. package/src/types/profile/index.ts +39 -39
  268. package/src/types/reviews/index.ts +132 -132
  269. package/src/types/tz-lookup.d.ts +4 -4
  270. package/src/types/user/index.ts +38 -38
  271. package/src/utils/TIMESTAMPS.md +176 -176
  272. package/src/utils/TimestampUtils.ts +241 -241
  273. package/src/utils/index.ts +1 -1
  274. package/src/validations/appointment.schema.ts +574 -574
  275. package/src/validations/calendar.schema.ts +225 -225
  276. package/src/validations/clinic.schema.ts +494 -494
  277. package/src/validations/common.schema.ts +25 -25
  278. package/src/validations/documentation-templates/index.ts +1 -1
  279. package/src/validations/documentation-templates/template.schema.ts +220 -220
  280. package/src/validations/documentation-templates.schema.ts +10 -10
  281. package/src/validations/index.ts +20 -20
  282. package/src/validations/media.schema.ts +10 -10
  283. package/src/validations/notification.schema.ts +90 -90
  284. package/src/validations/patient/aesthetic-analysis.schema.ts +55 -55
  285. package/src/validations/patient/medical-info.schema.ts +125 -125
  286. package/src/validations/patient/patient-requirements.schema.ts +84 -84
  287. package/src/validations/patient/token.schema.ts +29 -29
  288. package/src/validations/patient.schema.ts +217 -217
  289. package/src/validations/practitioner.schema.ts +222 -222
  290. package/src/validations/procedure-product.schema.ts +41 -41
  291. package/src/validations/procedure.schema.ts +124 -124
  292. package/src/validations/profile-info.schema.ts +41 -41
  293. package/src/validations/reviews.schema.ts +195 -195
  294. package/src/validations/schemas.ts +104 -104
  295. package/src/validations/shared.schema.ts +78 -78
@@ -1,481 +1,481 @@
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
- }
104
-
105
- /**
106
- * Interface for summarized patient review information linked to an appointment.
107
- */
108
- export interface PatientReviewInfo {
109
- reviewId: string; // ID of the full review document/record if stored elsewhere
110
- rating: number; // e.g., 1-5 stars
111
- comment?: string; // A short snippet or the full comment
112
- reviewedAt: Timestamp;
113
- }
114
-
115
- /**
116
- * Interface for before/after photos and notes per zone
117
- */
118
- export interface BeforeAfterPerZone {
119
- /** URL for before photo or null if not available */
120
- before: MediaResource | null;
121
- /** URL for after photo or null if not available */
122
- after: MediaResource | null;
123
- /** Optional note for the zone */
124
- afterNote?: string | null;
125
- beforeNote?: string | null;
126
- }
127
-
128
- /**
129
- * Interface for zone photo upload data
130
- */
131
- export interface ZonePhotoUploadData {
132
- appointmentId: string;
133
- zoneId: string;
134
- photoType: 'before' | 'after';
135
- file: File | Blob;
136
- notes?: string;
137
- }
138
-
139
- /**
140
- * Interface for zone item data (products or notes per zone)
141
- */
142
- export interface ZoneItemData {
143
- productId?: string;
144
- productName?: string;
145
- productBrandId?: string;
146
- productBrandName?: string;
147
- belongingProcedureId: string;
148
- type: 'item' | 'note';
149
- stage?: 'before' | 'after'; // Stage of the note/item: 'before' for planning notes, 'after' for treatment notes
150
- price?: number;
151
- currency?: Currency;
152
- unitOfMeasurement?: PricingMeasure;
153
- priceOverrideAmount?: number; // If set, takes precedence over price
154
- quantity?: number;
155
- parentZone: string; // Zone key in format "category.zone" (e.g., "face.forehead")
156
- subzones: string[];
157
- notes?: string;
158
- subtotal?: number;
159
- ionNumber?: string;
160
- createdAt?: string; // ISO timestamp
161
- updatedAt?: string; // ISO timestamp
162
- }
163
-
164
- /**
165
- * @deprecated Use ZoneItemData instead
166
- */
167
- export interface BillingPerZone {
168
- Product: string;
169
- ProductId: string | null;
170
- Quantity: number;
171
- UnitOfMeasurement: PricingMeasure;
172
- UnitPrice: number;
173
- UnitCurency: Currency;
174
- Subtotal: number;
175
- Note: string | null;
176
- IonNumber: string | null;
177
- }
178
-
179
- /**
180
- * Interface for final billing calculations of the appointment
181
- */
182
- export interface FinalBilling {
183
- /** Total of all subtotals from all zones */
184
- subtotalAll: number;
185
- /** Tax rate as percentage (e.g., 0.20 for 20%) */
186
- taxRate: number;
187
- /** Calculated tax amount */
188
- taxPrice: number;
189
- /** Final price including tax */
190
- finalPrice: number;
191
- /** Currency for the final billing */
192
- currency: Currency;
193
- }
194
-
195
- /**
196
- * Interface for product metadata in appointment
197
- */
198
- export interface AppointmentProductMetadata {
199
- productId: string;
200
- productName: string;
201
- brandId: string;
202
- brandName: string;
203
- procedureId: string;
204
- price: number;
205
- currency: Currency;
206
- unitOfMeasurement: PricingMeasure;
207
- }
208
-
209
- /**
210
- * Interface for extended procedures in appointment
211
- */
212
- export interface ExtendedProcedureInfo {
213
- procedureId: string;
214
- procedureName: string;
215
- procedureFamily?: ProcedureFamily;
216
- procedureCategoryId: string;
217
- procedureCategoryName: string;
218
- procedureSubCategoryId: string;
219
- procedureSubCategoryName: string;
220
- procedureTechnologyId: string;
221
- procedureTechnologyName: string;
222
- procedureProducts: Array<{
223
- productId: string;
224
- productName: string;
225
- brandId: string;
226
- brandName: string;
227
- }>;
228
- }
229
-
230
- export interface RecommendedProcedure {
231
- procedure: ExtendedProcedureInfo;
232
- note: string;
233
- timeframe: {
234
- value: number;
235
- unit: 'day' | 'week' | 'month' | 'year';
236
- };
237
- }
238
-
239
- /**
240
- * Interface for appointment metadata containing zone-specific information
241
- */
242
- export interface AppointmentMetadata {
243
- selectedZones: string[] | null;
244
- zonePhotos: Record<string, BeforeAfterPerZone[]> | null;
245
- zonesData?: Record<string, ZoneItemData[]> | null;
246
- appointmentProducts?: AppointmentProductMetadata[];
247
- extendedProcedures?: ExtendedProcedureInfo[];
248
- recommendedProcedures: RecommendedProcedure[]
249
- finalbilling: FinalBilling | null;
250
- finalizationNotes: string | null;
251
-
252
- /**
253
- * @deprecated Use zonesData instead
254
- */
255
- zoneBilling?: Record<string, BillingPerZone> | null;
256
- }
257
-
258
- /**
259
- * Represents a booked appointment, aggregating key information and relevant procedure rules.
260
- */
261
- export interface Appointment {
262
- /** Unique identifier for the appointment */
263
- id: string;
264
- /** Reference to the associated CalendarEvent */
265
- calendarEventId: string;
266
-
267
- /** ID of the clinic branch */
268
- clinicBranchId: string;
269
- /** Aggregated clinic information (snapshot) */
270
- clinicInfo: ClinicInfo;
271
- /** IANA timezone of the clinic */
272
- clinic_tz: string;
273
-
274
- /** ID of the practitioner */
275
- practitionerId: string;
276
- /** Aggregated practitioner information (snapshot) */
277
- practitionerInfo: PractitionerProfileInfo;
278
-
279
- /** ID of the patient */
280
- patientId: string;
281
- /** Aggregated patient information (snapshot) */
282
- patientInfo: PatientProfileInfo;
283
-
284
- /** ID of the procedure */
285
- procedureId: string;
286
- /** Aggregated procedure information including product/brand (snapshot) */
287
- procedureInfo: ProcedureSummaryInfo; // Aggregated procedure information
288
- /** Extended procedure information */
289
- procedureExtendedInfo: ProcedureExtendedInfo; // Aggregated extended procedure information
290
-
291
- /** Status of the appointment */
292
- status: AppointmentStatus;
293
-
294
- /** Timestamps */
295
- bookingTime: Timestamp;
296
- confirmationTime?: Timestamp | null;
297
- cancellationTime?: Timestamp | null;
298
- rescheduleTime?: Timestamp | null;
299
- appointmentStartTime: Timestamp;
300
- appointmentEndTime: Timestamp;
301
- procedureActualStartTime?: Timestamp | null; // NEW: Actual start time of the procedure
302
- actualDurationMinutes?: number;
303
-
304
- /** Cancellation Details */
305
- cancellationReason?: string | null;
306
- canceledBy?: 'patient' | 'clinic' | 'practitioner' | 'system';
307
-
308
- /** Notes */
309
- internalNotes?: string | null;
310
- patientNotes?: string | null;
311
-
312
- /** Payment Details */
313
- cost: number;
314
- currency: Currency;
315
- paymentStatus: PaymentStatus;
316
- paymentTransactionId?: string | null;
317
-
318
- /** Procedure-related conditions and requirements */
319
- blockingConditions: BlockingCondition[];
320
- contraindications: ContraindicationDynamic[];
321
- preProcedureRequirements: Requirement[];
322
- postProcedureRequirements: Requirement[];
323
-
324
- /** Tracking information for requirements completion */
325
- completedPreRequirements?: string[]; // IDs of completed pre-requirements
326
- completedPostRequirements?: string[]; // IDs of completed post-requirements
327
-
328
- /** NEW: Linked forms (consent, procedure-specific forms, etc.) */
329
- linkedFormIds?: string[];
330
- linkedForms?: LinkedFormInfo[];
331
- 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)
332
-
333
- /** NEW: Media items (before/after photos, scanned documents, etc.) */
334
- media?: AppointmentMediaItem[];
335
-
336
- /** NEW: Information about the patient's review for this appointment */
337
- reviewInfo?: PatientReviewInfo | null;
338
-
339
- /** NEW: Details about the finalization of the appointment by the practitioner */
340
- finalizedDetails?: {
341
- by: string; // Practitioner User ID
342
- at: Timestamp;
343
- notes?: string;
344
- };
345
-
346
- /** Timestamps for record creation and updates */
347
- createdAt: Timestamp;
348
- updatedAt: Timestamp;
349
-
350
- /** Recurring appointment information */
351
- isRecurring?: boolean;
352
- recurringAppointmentId?: string | null;
353
-
354
- /** NEW: Flag for soft deletion or archiving */
355
- isArchived?: boolean;
356
-
357
- /** NEW: Metadata for the appointment - used for area selection and photos */
358
- metadata?: AppointmentMetadata;
359
- }
360
-
361
- /**
362
- * Data needed to create a new Appointment
363
- */
364
- export interface CreateAppointmentData {
365
- clinicBranchId: string;
366
- practitionerId: string;
367
- patientId: string;
368
- procedureId: string;
369
- appointmentStartTime: Timestamp;
370
- appointmentEndTime: Timestamp;
371
- cost: number;
372
- currency: Currency;
373
- patientNotes?: string | null;
374
- initialStatus: AppointmentStatus;
375
- initialPaymentStatus?: PaymentStatus; // Defaults to UNPAID if not provided
376
- clinic_tz: string;
377
- }
378
-
379
- /**
380
- * Data needed to create a new Appointment via CreateAppointmentHttp method
381
- */
382
- export interface CreateAppointmentHttpData {
383
- patientId: string;
384
- procedureId: string;
385
- appointmentStartTime: Timestamp;
386
- appointmentEndTime: Timestamp;
387
- patientNotes?: string | null;
388
- }
389
-
390
- /**
391
- * Data allowed for updating an Appointment
392
- */
393
- export interface UpdateAppointmentData {
394
- status?: AppointmentStatus;
395
- confirmationTime?: Timestamp | FieldValue | null;
396
- cancellationTime?: Timestamp | FieldValue | null;
397
- rescheduleTime?: Timestamp | FieldValue | null;
398
- procedureActualStartTime?: Timestamp | FieldValue | null; // NEW
399
- actualDurationMinutes?: number;
400
- cancellationReason?: string | null;
401
- canceledBy?: 'patient' | 'clinic' | 'practitioner' | 'system';
402
- internalNotes?: string | null;
403
- patientNotes?: string | FieldValue | null; // Allow FieldValue for deleting
404
- paymentStatus?: PaymentStatus;
405
- paymentTransactionId?: string | FieldValue | null;
406
- completedPreRequirements?: string[] | FieldValue; // Allow FieldValue for arrayUnion/arrayRemove
407
- completedPostRequirements?: string[] | FieldValue;
408
- appointmentStartTime?: Timestamp; // For rescheduling
409
- appointmentEndTime?: Timestamp; // For rescheduling
410
- calendarEventId?: string; // If calendar event needs to be re-linked
411
- cost?: number; // If cost is adjusted
412
- clinicBranchId?: string; // If appointment is moved to another branch (complex scenario)
413
- practitionerId?: string; // If practitioner is changed
414
- clinic_tz?: string;
415
-
416
- /** NEW: For updating linked forms - typically managed by dedicated methods */
417
- linkedFormIds?: string[] | FieldValue;
418
- linkedForms?: LinkedFormInfo[] | FieldValue;
419
-
420
- /** NEW: For updating media items - typically managed by dedicated methods */
421
- media?: AppointmentMediaItem[] | FieldValue;
422
-
423
- /** NEW: For adding/updating review information */
424
- reviewInfo?: PatientReviewInfo | FieldValue | null;
425
-
426
- /** NEW: For setting practitioner finalization details */
427
- finalizedDetails?: { by: string; at: Timestamp; notes?: string } | FieldValue;
428
-
429
- /** NEW: For archiving/unarchiving */
430
- isArchived?: boolean;
431
-
432
- updatedAt?: FieldValue; // To set server timestamp
433
-
434
- /** NEW: For updating metadata */
435
- metadata?: AppointmentMetadata;
436
- }
437
-
438
- /**
439
- * Parameters for searching appointments
440
- */
441
- export interface SearchAppointmentsParams {
442
- patientId?: string;
443
- practitionerId?: string;
444
- clinicBranchId?: string;
445
- startDate?: Date;
446
- endDate?: Date;
447
- status?: AppointmentStatus | AppointmentStatus[];
448
- limit?: number;
449
- startAfter?: any;
450
- }
451
-
452
- /** Firestore collection name */
453
- export const APPOINTMENTS_COLLECTION = 'appointments';
454
-
455
- /**
456
- * Interface for next steps recommendation with context about when and who suggested it
457
- */
458
- export interface NextStepsRecommendation {
459
- /** Unique identifier for this recommendation (appointmentId + recommendationIndex) */
460
- id: string;
461
- /** The recommended procedure details */
462
- recommendedProcedure: RecommendedProcedure;
463
- /** ID of the appointment where this was recommended */
464
- appointmentId: string;
465
- /** Date of the appointment when this was recommended */
466
- appointmentDate: Timestamp;
467
- /** ID of the practitioner who made the recommendation */
468
- practitionerId: string;
469
- /** Name of the practitioner who made the recommendation */
470
- practitionerName: string;
471
- /** ID of the clinic where the appointment took place */
472
- clinicBranchId: string;
473
- /** Name of the clinic where the appointment took place */
474
- clinicName: string;
475
- /** Status of the appointment when recommendation was made */
476
- appointmentStatus: AppointmentStatus;
477
- /** Whether this recommendation has been dismissed by the patient */
478
- isDismissed?: boolean;
479
- /** When the recommendation was dismissed (if dismissed) */
480
- 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 { 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
+ }
104
+
105
+ /**
106
+ * Interface for summarized patient review information linked to an appointment.
107
+ */
108
+ export interface PatientReviewInfo {
109
+ reviewId: string; // ID of the full review document/record if stored elsewhere
110
+ rating: number; // e.g., 1-5 stars
111
+ comment?: string; // A short snippet or the full comment
112
+ reviewedAt: Timestamp;
113
+ }
114
+
115
+ /**
116
+ * Interface for before/after photos and notes per zone
117
+ */
118
+ export interface BeforeAfterPerZone {
119
+ /** URL for before photo or null if not available */
120
+ before: MediaResource | null;
121
+ /** URL for after photo or null if not available */
122
+ after: MediaResource | null;
123
+ /** Optional note for the zone */
124
+ afterNote?: string | null;
125
+ beforeNote?: string | null;
126
+ }
127
+
128
+ /**
129
+ * Interface for zone photo upload data
130
+ */
131
+ export interface ZonePhotoUploadData {
132
+ appointmentId: string;
133
+ zoneId: string;
134
+ photoType: 'before' | 'after';
135
+ file: File | Blob;
136
+ notes?: string;
137
+ }
138
+
139
+ /**
140
+ * Interface for zone item data (products or notes per zone)
141
+ */
142
+ export interface ZoneItemData {
143
+ productId?: string;
144
+ productName?: string;
145
+ productBrandId?: string;
146
+ productBrandName?: string;
147
+ belongingProcedureId: string;
148
+ type: 'item' | 'note';
149
+ stage?: 'before' | 'after'; // Stage of the note/item: 'before' for planning notes, 'after' for treatment notes
150
+ price?: number;
151
+ currency?: Currency;
152
+ unitOfMeasurement?: PricingMeasure;
153
+ priceOverrideAmount?: number; // If set, takes precedence over price
154
+ quantity?: number;
155
+ parentZone: string; // Zone key in format "category.zone" (e.g., "face.forehead")
156
+ subzones: string[];
157
+ notes?: string;
158
+ subtotal?: number;
159
+ ionNumber?: string;
160
+ createdAt?: string; // ISO timestamp
161
+ updatedAt?: string; // ISO timestamp
162
+ }
163
+
164
+ /**
165
+ * @deprecated Use ZoneItemData instead
166
+ */
167
+ export interface BillingPerZone {
168
+ Product: string;
169
+ ProductId: string | null;
170
+ Quantity: number;
171
+ UnitOfMeasurement: PricingMeasure;
172
+ UnitPrice: number;
173
+ UnitCurency: Currency;
174
+ Subtotal: number;
175
+ Note: string | null;
176
+ IonNumber: string | null;
177
+ }
178
+
179
+ /**
180
+ * Interface for final billing calculations of the appointment
181
+ */
182
+ export interface FinalBilling {
183
+ /** Total of all subtotals from all zones */
184
+ subtotalAll: number;
185
+ /** Tax rate as percentage (e.g., 0.20 for 20%) */
186
+ taxRate: number;
187
+ /** Calculated tax amount */
188
+ taxPrice: number;
189
+ /** Final price including tax */
190
+ finalPrice: number;
191
+ /** Currency for the final billing */
192
+ currency: Currency;
193
+ }
194
+
195
+ /**
196
+ * Interface for product metadata in appointment
197
+ */
198
+ export interface AppointmentProductMetadata {
199
+ productId: string;
200
+ productName: string;
201
+ brandId: string;
202
+ brandName: string;
203
+ procedureId: string;
204
+ price: number;
205
+ currency: Currency;
206
+ unitOfMeasurement: PricingMeasure;
207
+ }
208
+
209
+ /**
210
+ * Interface for extended procedures in appointment
211
+ */
212
+ export interface ExtendedProcedureInfo {
213
+ procedureId: string;
214
+ procedureName: string;
215
+ procedureFamily?: ProcedureFamily;
216
+ procedureCategoryId: string;
217
+ procedureCategoryName: string;
218
+ procedureSubCategoryId: string;
219
+ procedureSubCategoryName: string;
220
+ procedureTechnologyId: string;
221
+ procedureTechnologyName: string;
222
+ procedureProducts: Array<{
223
+ productId: string;
224
+ productName: string;
225
+ brandId: string;
226
+ brandName: string;
227
+ }>;
228
+ }
229
+
230
+ export interface RecommendedProcedure {
231
+ procedure: ExtendedProcedureInfo;
232
+ note: string;
233
+ timeframe: {
234
+ value: number;
235
+ unit: 'day' | 'week' | 'month' | 'year';
236
+ };
237
+ }
238
+
239
+ /**
240
+ * Interface for appointment metadata containing zone-specific information
241
+ */
242
+ export interface AppointmentMetadata {
243
+ selectedZones: string[] | null;
244
+ zonePhotos: Record<string, BeforeAfterPerZone[]> | null;
245
+ zonesData?: Record<string, ZoneItemData[]> | null;
246
+ appointmentProducts?: AppointmentProductMetadata[];
247
+ extendedProcedures?: ExtendedProcedureInfo[];
248
+ recommendedProcedures: RecommendedProcedure[]
249
+ finalbilling: FinalBilling | null;
250
+ finalizationNotes: string | null;
251
+
252
+ /**
253
+ * @deprecated Use zonesData instead
254
+ */
255
+ zoneBilling?: Record<string, BillingPerZone> | null;
256
+ }
257
+
258
+ /**
259
+ * Represents a booked appointment, aggregating key information and relevant procedure rules.
260
+ */
261
+ export interface Appointment {
262
+ /** Unique identifier for the appointment */
263
+ id: string;
264
+ /** Reference to the associated CalendarEvent */
265
+ calendarEventId: string;
266
+
267
+ /** ID of the clinic branch */
268
+ clinicBranchId: string;
269
+ /** Aggregated clinic information (snapshot) */
270
+ clinicInfo: ClinicInfo;
271
+ /** IANA timezone of the clinic */
272
+ clinic_tz: string;
273
+
274
+ /** ID of the practitioner */
275
+ practitionerId: string;
276
+ /** Aggregated practitioner information (snapshot) */
277
+ practitionerInfo: PractitionerProfileInfo;
278
+
279
+ /** ID of the patient */
280
+ patientId: string;
281
+ /** Aggregated patient information (snapshot) */
282
+ patientInfo: PatientProfileInfo;
283
+
284
+ /** ID of the procedure */
285
+ procedureId: string;
286
+ /** Aggregated procedure information including product/brand (snapshot) */
287
+ procedureInfo: ProcedureSummaryInfo; // Aggregated procedure information
288
+ /** Extended procedure information */
289
+ procedureExtendedInfo: ProcedureExtendedInfo; // Aggregated extended procedure information
290
+
291
+ /** Status of the appointment */
292
+ status: AppointmentStatus;
293
+
294
+ /** Timestamps */
295
+ bookingTime: Timestamp;
296
+ confirmationTime?: Timestamp | null;
297
+ cancellationTime?: Timestamp | null;
298
+ rescheduleTime?: Timestamp | null;
299
+ appointmentStartTime: Timestamp;
300
+ appointmentEndTime: Timestamp;
301
+ procedureActualStartTime?: Timestamp | null; // NEW: Actual start time of the procedure
302
+ actualDurationMinutes?: number;
303
+
304
+ /** Cancellation Details */
305
+ cancellationReason?: string | null;
306
+ canceledBy?: 'patient' | 'clinic' | 'practitioner' | 'system';
307
+
308
+ /** Notes */
309
+ internalNotes?: string | null;
310
+ patientNotes?: string | null;
311
+
312
+ /** Payment Details */
313
+ cost: number;
314
+ currency: Currency;
315
+ paymentStatus: PaymentStatus;
316
+ paymentTransactionId?: string | null;
317
+
318
+ /** Procedure-related conditions and requirements */
319
+ blockingConditions: BlockingCondition[];
320
+ contraindications: ContraindicationDynamic[];
321
+ preProcedureRequirements: Requirement[];
322
+ postProcedureRequirements: Requirement[];
323
+
324
+ /** Tracking information for requirements completion */
325
+ completedPreRequirements?: string[]; // IDs of completed pre-requirements
326
+ completedPostRequirements?: string[]; // IDs of completed post-requirements
327
+
328
+ /** NEW: Linked forms (consent, procedure-specific forms, etc.) */
329
+ linkedFormIds?: string[];
330
+ linkedForms?: LinkedFormInfo[];
331
+ 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)
332
+
333
+ /** NEW: Media items (before/after photos, scanned documents, etc.) */
334
+ media?: AppointmentMediaItem[];
335
+
336
+ /** NEW: Information about the patient's review for this appointment */
337
+ reviewInfo?: PatientReviewInfo | null;
338
+
339
+ /** NEW: Details about the finalization of the appointment by the practitioner */
340
+ finalizedDetails?: {
341
+ by: string; // Practitioner User ID
342
+ at: Timestamp;
343
+ notes?: string;
344
+ };
345
+
346
+ /** Timestamps for record creation and updates */
347
+ createdAt: Timestamp;
348
+ updatedAt: Timestamp;
349
+
350
+ /** Recurring appointment information */
351
+ isRecurring?: boolean;
352
+ recurringAppointmentId?: string | null;
353
+
354
+ /** NEW: Flag for soft deletion or archiving */
355
+ isArchived?: boolean;
356
+
357
+ /** NEW: Metadata for the appointment - used for area selection and photos */
358
+ metadata?: AppointmentMetadata;
359
+ }
360
+
361
+ /**
362
+ * Data needed to create a new Appointment
363
+ */
364
+ export interface CreateAppointmentData {
365
+ clinicBranchId: string;
366
+ practitionerId: string;
367
+ patientId: string;
368
+ procedureId: string;
369
+ appointmentStartTime: Timestamp;
370
+ appointmentEndTime: Timestamp;
371
+ cost: number;
372
+ currency: Currency;
373
+ patientNotes?: string | null;
374
+ initialStatus: AppointmentStatus;
375
+ initialPaymentStatus?: PaymentStatus; // Defaults to UNPAID if not provided
376
+ clinic_tz: string;
377
+ }
378
+
379
+ /**
380
+ * Data needed to create a new Appointment via CreateAppointmentHttp method
381
+ */
382
+ export interface CreateAppointmentHttpData {
383
+ patientId: string;
384
+ procedureId: string;
385
+ appointmentStartTime: Timestamp;
386
+ appointmentEndTime: Timestamp;
387
+ patientNotes?: string | null;
388
+ }
389
+
390
+ /**
391
+ * Data allowed for updating an Appointment
392
+ */
393
+ export interface UpdateAppointmentData {
394
+ status?: AppointmentStatus;
395
+ confirmationTime?: Timestamp | FieldValue | null;
396
+ cancellationTime?: Timestamp | FieldValue | null;
397
+ rescheduleTime?: Timestamp | FieldValue | null;
398
+ procedureActualStartTime?: Timestamp | FieldValue | null; // NEW
399
+ actualDurationMinutes?: number;
400
+ cancellationReason?: string | null;
401
+ canceledBy?: 'patient' | 'clinic' | 'practitioner' | 'system';
402
+ internalNotes?: string | null;
403
+ patientNotes?: string | FieldValue | null; // Allow FieldValue for deleting
404
+ paymentStatus?: PaymentStatus;
405
+ paymentTransactionId?: string | FieldValue | null;
406
+ completedPreRequirements?: string[] | FieldValue; // Allow FieldValue for arrayUnion/arrayRemove
407
+ completedPostRequirements?: string[] | FieldValue;
408
+ appointmentStartTime?: Timestamp; // For rescheduling
409
+ appointmentEndTime?: Timestamp; // For rescheduling
410
+ calendarEventId?: string; // If calendar event needs to be re-linked
411
+ cost?: number; // If cost is adjusted
412
+ clinicBranchId?: string; // If appointment is moved to another branch (complex scenario)
413
+ practitionerId?: string; // If practitioner is changed
414
+ clinic_tz?: string;
415
+
416
+ /** NEW: For updating linked forms - typically managed by dedicated methods */
417
+ linkedFormIds?: string[] | FieldValue;
418
+ linkedForms?: LinkedFormInfo[] | FieldValue;
419
+
420
+ /** NEW: For updating media items - typically managed by dedicated methods */
421
+ media?: AppointmentMediaItem[] | FieldValue;
422
+
423
+ /** NEW: For adding/updating review information */
424
+ reviewInfo?: PatientReviewInfo | FieldValue | null;
425
+
426
+ /** NEW: For setting practitioner finalization details */
427
+ finalizedDetails?: { by: string; at: Timestamp; notes?: string } | FieldValue;
428
+
429
+ /** NEW: For archiving/unarchiving */
430
+ isArchived?: boolean;
431
+
432
+ updatedAt?: FieldValue; // To set server timestamp
433
+
434
+ /** NEW: For updating metadata */
435
+ metadata?: AppointmentMetadata;
436
+ }
437
+
438
+ /**
439
+ * Parameters for searching appointments
440
+ */
441
+ export interface SearchAppointmentsParams {
442
+ patientId?: string;
443
+ practitionerId?: string;
444
+ clinicBranchId?: string;
445
+ startDate?: Date;
446
+ endDate?: Date;
447
+ status?: AppointmentStatus | AppointmentStatus[];
448
+ limit?: number;
449
+ startAfter?: any;
450
+ }
451
+
452
+ /** Firestore collection name */
453
+ export const APPOINTMENTS_COLLECTION = 'appointments';
454
+
455
+ /**
456
+ * Interface for next steps recommendation with context about when and who suggested it
457
+ */
458
+ export interface NextStepsRecommendation {
459
+ /** Unique identifier for this recommendation (appointmentId + recommendationIndex) */
460
+ id: string;
461
+ /** The recommended procedure details */
462
+ recommendedProcedure: RecommendedProcedure;
463
+ /** ID of the appointment where this was recommended */
464
+ appointmentId: string;
465
+ /** Date of the appointment when this was recommended */
466
+ appointmentDate: Timestamp;
467
+ /** ID of the practitioner who made the recommendation */
468
+ practitionerId: string;
469
+ /** Name of the practitioner who made the recommendation */
470
+ practitionerName: string;
471
+ /** ID of the clinic where the appointment took place */
472
+ clinicBranchId: string;
473
+ /** Name of the clinic where the appointment took place */
474
+ clinicName: string;
475
+ /** Status of the appointment when recommendation was made */
476
+ appointmentStatus: AppointmentStatus;
477
+ /** Whether this recommendation has been dismissed by the patient */
478
+ isDismissed?: boolean;
479
+ /** When the recommendation was dismissed (if dismissed) */
480
+ dismissedAt?: Timestamp | null;
481
481
  }