@blackcode_sa/metaestetics-api 1.12.65 → 1.12.67

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 (273) hide show
  1. package/dist/admin/index.d.mts +2 -0
  2. package/dist/admin/index.d.ts +2 -0
  3. package/dist/admin/index.js +45 -4
  4. package/dist/admin/index.mjs +45 -4
  5. package/dist/backoffice/index.d.mts +33 -0
  6. package/dist/backoffice/index.d.ts +33 -0
  7. package/dist/backoffice/index.js +63 -0
  8. package/dist/backoffice/index.mjs +63 -0
  9. package/dist/index.d.mts +35 -0
  10. package/dist/index.d.ts +35 -0
  11. package/dist/index.js +116 -11
  12. package/dist/index.mjs +116 -11
  13. package/package.json +119 -119
  14. package/src/__mocks__/firstore.ts +10 -10
  15. package/src/admin/aggregation/README.md +79 -79
  16. package/src/admin/aggregation/appointment/README.md +128 -128
  17. package/src/admin/aggregation/appointment/appointment.aggregation.service.ts +1844 -1844
  18. package/src/admin/aggregation/appointment/index.ts +1 -1
  19. package/src/admin/aggregation/clinic/README.md +52 -52
  20. package/src/admin/aggregation/clinic/clinic.aggregation.service.ts +703 -703
  21. package/src/admin/aggregation/clinic/index.ts +1 -1
  22. package/src/admin/aggregation/forms/README.md +13 -13
  23. package/src/admin/aggregation/forms/filled-forms.aggregation.service.ts +322 -322
  24. package/src/admin/aggregation/forms/index.ts +1 -1
  25. package/src/admin/aggregation/index.ts +8 -8
  26. package/src/admin/aggregation/patient/README.md +27 -27
  27. package/src/admin/aggregation/patient/index.ts +1 -1
  28. package/src/admin/aggregation/patient/patient.aggregation.service.ts +141 -141
  29. package/src/admin/aggregation/practitioner/README.md +42 -42
  30. package/src/admin/aggregation/practitioner/index.ts +1 -1
  31. package/src/admin/aggregation/practitioner/practitioner.aggregation.service.ts +433 -433
  32. package/src/admin/aggregation/practitioner-invite/index.ts +1 -1
  33. package/src/admin/aggregation/practitioner-invite/practitioner-invite.aggregation.service.ts +961 -961
  34. package/src/admin/aggregation/procedure/README.md +43 -43
  35. package/src/admin/aggregation/procedure/index.ts +1 -1
  36. package/src/admin/aggregation/procedure/procedure.aggregation.service.ts +702 -702
  37. package/src/admin/aggregation/reviews/index.ts +1 -1
  38. package/src/admin/aggregation/reviews/reviews.aggregation.service.ts +689 -641
  39. package/src/admin/booking/README.md +125 -125
  40. package/src/admin/booking/booking.admin.ts +1037 -1037
  41. package/src/admin/booking/booking.calculator.ts +712 -712
  42. package/src/admin/booking/booking.types.ts +59 -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 +7 -7
  46. package/src/admin/calendar/calendar.admin.service.ts +345 -345
  47. package/src/admin/calendar/index.ts +1 -1
  48. package/src/admin/documentation-templates/document-manager.admin.ts +260 -260
  49. package/src/admin/documentation-templates/index.ts +1 -1
  50. package/src/admin/free-consultation/free-consultation-utils.admin.ts +148 -148
  51. package/src/admin/free-consultation/index.ts +1 -1
  52. package/src/admin/index.ts +75 -75
  53. package/src/admin/logger/index.ts +78 -78
  54. package/src/admin/mailing/README.md +95 -95
  55. package/src/admin/mailing/appointment/appointment.mailing.service.ts +732 -732
  56. package/src/admin/mailing/appointment/index.ts +1 -1
  57. package/src/admin/mailing/appointment/templates/patient/appointment-confirmed.html +40 -40
  58. package/src/admin/mailing/base.mailing.service.ts +208 -208
  59. package/src/admin/mailing/index.ts +3 -3
  60. package/src/admin/mailing/practitionerInvite/existing-practitioner-invite.mailing.ts +611 -611
  61. package/src/admin/mailing/practitionerInvite/index.ts +2 -2
  62. package/src/admin/mailing/practitionerInvite/practitionerInvite.mailing.ts +395 -395
  63. package/src/admin/mailing/practitionerInvite/templates/existing-practitioner-invitation.template.ts +155 -155
  64. package/src/admin/mailing/practitionerInvite/templates/invitation.template.ts +101 -101
  65. package/src/admin/mailing/practitionerInvite/templates/invite-accepted-notification.template.ts +228 -228
  66. package/src/admin/mailing/practitionerInvite/templates/invite-rejected-notification.template.ts +242 -242
  67. package/src/admin/notifications/index.ts +1 -1
  68. package/src/admin/notifications/notifications.admin.ts +710 -710
  69. package/src/admin/requirements/README.md +128 -128
  70. package/src/admin/requirements/index.ts +1 -1
  71. package/src/admin/requirements/patient-requirements.admin.service.ts +475 -475
  72. package/src/admin/users/index.ts +1 -1
  73. package/src/admin/users/user-profile.admin.ts +405 -405
  74. package/src/backoffice/constants/certification.constants.ts +13 -13
  75. package/src/backoffice/constants/index.ts +1 -1
  76. package/src/backoffice/errors/backoffice.errors.ts +181 -181
  77. package/src/backoffice/errors/index.ts +1 -1
  78. package/src/backoffice/expo-safe/README.md +26 -26
  79. package/src/backoffice/expo-safe/index.ts +41 -41
  80. package/src/backoffice/index.ts +5 -5
  81. package/src/backoffice/services/FIXES_README.md +102 -102
  82. package/src/backoffice/services/README.md +40 -40
  83. package/src/backoffice/services/brand.service.ts +256 -256
  84. package/src/backoffice/services/category.service.ts +341 -318
  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 +417 -395
  92. package/src/backoffice/services/technology.service.ts +1104 -1083
  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 -62
  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 -163
  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 +200 -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/appointment/README.md +17 -17
  139. package/src/services/appointment/appointment.service.ts +2505 -2505
  140. package/src/services/appointment/index.ts +1 -1
  141. package/src/services/appointment/utils/appointment.utils.ts +552 -552
  142. package/src/services/appointment/utils/extended-procedure.utils.ts +314 -314
  143. package/src/services/appointment/utils/form-initialization.utils.ts +225 -225
  144. package/src/services/appointment/utils/recommended-procedure.utils.ts +195 -195
  145. package/src/services/appointment/utils/zone-management.utils.ts +353 -353
  146. package/src/services/appointment/utils/zone-photo.utils.ts +152 -152
  147. package/src/services/auth/auth.service.ts +989 -989
  148. package/src/services/auth/auth.v2.service.ts +961 -961
  149. package/src/services/auth/index.ts +7 -7
  150. package/src/services/auth/utils/error.utils.ts +90 -90
  151. package/src/services/auth/utils/firebase.utils.ts +49 -49
  152. package/src/services/auth/utils/index.ts +21 -21
  153. package/src/services/auth/utils/practitioner.utils.ts +125 -125
  154. package/src/services/base.service.ts +41 -41
  155. package/src/services/calendar/calendar.service.ts +1077 -1077
  156. package/src/services/calendar/calendar.v2.service.ts +1683 -1683
  157. package/src/services/calendar/calendar.v3.service.ts +313 -313
  158. package/src/services/calendar/externalCalendar.service.ts +178 -178
  159. package/src/services/calendar/index.ts +5 -5
  160. package/src/services/calendar/synced-calendars.service.ts +743 -743
  161. package/src/services/calendar/utils/appointment.utils.ts +265 -265
  162. package/src/services/calendar/utils/calendar-event.utils.ts +646 -646
  163. package/src/services/calendar/utils/clinic.utils.ts +237 -237
  164. package/src/services/calendar/utils/docs.utils.ts +157 -157
  165. package/src/services/calendar/utils/google-calendar.utils.ts +697 -697
  166. package/src/services/calendar/utils/index.ts +8 -8
  167. package/src/services/calendar/utils/patient.utils.ts +198 -198
  168. package/src/services/calendar/utils/practitioner.utils.ts +221 -221
  169. package/src/services/calendar/utils/synced-calendar.utils.ts +472 -472
  170. package/src/services/clinic/README.md +204 -204
  171. package/src/services/clinic/__tests__/clinic-admin.service.test.ts +287 -287
  172. package/src/services/clinic/__tests__/clinic-group.service.test.ts +352 -352
  173. package/src/services/clinic/__tests__/clinic.service.test.ts +354 -354
  174. package/src/services/clinic/billing-transactions.service.ts +217 -217
  175. package/src/services/clinic/clinic-admin.service.ts +202 -202
  176. package/src/services/clinic/clinic-group.service.ts +310 -310
  177. package/src/services/clinic/clinic.service.ts +708 -708
  178. package/src/services/clinic/index.ts +5 -5
  179. package/src/services/clinic/practitioner-invite.service.ts +519 -519
  180. package/src/services/clinic/utils/admin.utils.ts +551 -551
  181. package/src/services/clinic/utils/clinic-group.utils.ts +646 -646
  182. package/src/services/clinic/utils/clinic.utils.ts +949 -949
  183. package/src/services/clinic/utils/filter.utils.d.ts +23 -23
  184. package/src/services/clinic/utils/filter.utils.ts +446 -446
  185. package/src/services/clinic/utils/index.ts +11 -11
  186. package/src/services/clinic/utils/photos.utils.ts +188 -188
  187. package/src/services/clinic/utils/search.utils.ts +84 -84
  188. package/src/services/clinic/utils/tag.utils.ts +124 -124
  189. package/src/services/documentation-templates/documentation-template.service.ts +537 -537
  190. package/src/services/documentation-templates/filled-document.service.ts +587 -587
  191. package/src/services/documentation-templates/index.ts +2 -2
  192. package/src/services/index.ts +13 -13
  193. package/src/services/media/index.ts +1 -1
  194. package/src/services/media/media.service.ts +418 -418
  195. package/src/services/notifications/__tests__/notification.service.test.ts +242 -242
  196. package/src/services/notifications/index.ts +1 -1
  197. package/src/services/notifications/notification.service.ts +215 -215
  198. package/src/services/patient/README.md +48 -48
  199. package/src/services/patient/To-Do.md +43 -43
  200. package/src/services/patient/__tests__/patient.service.test.ts +294 -294
  201. package/src/services/patient/index.ts +2 -2
  202. package/src/services/patient/patient.service.ts +883 -883
  203. package/src/services/patient/patientRequirements.service.ts +285 -285
  204. package/src/services/patient/utils/aesthetic-analysis.utils.ts +176 -176
  205. package/src/services/patient/utils/clinic.utils.ts +80 -80
  206. package/src/services/patient/utils/docs.utils.ts +142 -142
  207. package/src/services/patient/utils/index.ts +9 -9
  208. package/src/services/patient/utils/location.utils.ts +126 -126
  209. package/src/services/patient/utils/medical-stuff.utils.ts +143 -143
  210. package/src/services/patient/utils/medical.utils.ts +458 -458
  211. package/src/services/patient/utils/practitioner.utils.ts +260 -260
  212. package/src/services/patient/utils/profile.utils.ts +510 -510
  213. package/src/services/patient/utils/sensitive.utils.ts +260 -260
  214. package/src/services/patient/utils/token.utils.ts +211 -211
  215. package/src/services/practitioner/README.md +145 -145
  216. package/src/services/practitioner/index.ts +1 -1
  217. package/src/services/practitioner/practitioner.service.ts +1742 -1742
  218. package/src/services/procedure/README.md +163 -163
  219. package/src/services/procedure/index.ts +1 -1
  220. package/src/services/procedure/procedure.service.ts +1715 -1715
  221. package/src/services/reviews/index.ts +1 -1
  222. package/src/services/reviews/reviews.service.ts +683 -636
  223. package/src/services/user/index.ts +1 -1
  224. package/src/services/user/user.service.ts +489 -489
  225. package/src/services/user/user.v2.service.ts +466 -466
  226. package/src/types/appointment/index.ts +480 -480
  227. package/src/types/calendar/index.ts +258 -258
  228. package/src/types/calendar/synced-calendar.types.ts +66 -66
  229. package/src/types/clinic/index.ts +489 -489
  230. package/src/types/clinic/practitioner-invite.types.ts +91 -91
  231. package/src/types/clinic/preferences.types.ts +159 -159
  232. package/src/types/clinic/to-do +3 -3
  233. package/src/types/documentation-templates/index.ts +308 -308
  234. package/src/types/index.ts +44 -44
  235. package/src/types/notifications/README.md +77 -77
  236. package/src/types/notifications/index.ts +265 -265
  237. package/src/types/patient/aesthetic-analysis.types.ts +66 -66
  238. package/src/types/patient/allergies.ts +58 -58
  239. package/src/types/patient/index.ts +275 -275
  240. package/src/types/patient/medical-info.types.ts +152 -152
  241. package/src/types/patient/patient-requirements.ts +92 -92
  242. package/src/types/patient/token.types.ts +61 -61
  243. package/src/types/practitioner/index.ts +206 -206
  244. package/src/types/procedure/index.ts +181 -181
  245. package/src/types/profile/index.ts +39 -39
  246. package/src/types/reviews/index.ts +132 -130
  247. package/src/types/tz-lookup.d.ts +4 -4
  248. package/src/types/user/index.ts +38 -38
  249. package/src/utils/TIMESTAMPS.md +176 -176
  250. package/src/utils/TimestampUtils.ts +241 -241
  251. package/src/utils/index.ts +1 -1
  252. package/src/validations/appointment.schema.ts +574 -574
  253. package/src/validations/calendar.schema.ts +225 -225
  254. package/src/validations/clinic.schema.ts +493 -493
  255. package/src/validations/common.schema.ts +25 -25
  256. package/src/validations/documentation-templates/index.ts +1 -1
  257. package/src/validations/documentation-templates/template.schema.ts +220 -220
  258. package/src/validations/documentation-templates.schema.ts +10 -10
  259. package/src/validations/index.ts +20 -20
  260. package/src/validations/media.schema.ts +10 -10
  261. package/src/validations/notification.schema.ts +90 -90
  262. package/src/validations/patient/aesthetic-analysis.schema.ts +55 -55
  263. package/src/validations/patient/medical-info.schema.ts +125 -125
  264. package/src/validations/patient/patient-requirements.schema.ts +84 -84
  265. package/src/validations/patient/token.schema.ts +29 -29
  266. package/src/validations/patient.schema.ts +217 -217
  267. package/src/validations/practitioner.schema.ts +222 -222
  268. package/src/validations/procedure-product.schema.ts +41 -41
  269. package/src/validations/procedure.schema.ts +124 -124
  270. package/src/validations/profile-info.schema.ts +41 -41
  271. package/src/validations/reviews.schema.ts +195 -189
  272. package/src/validations/schemas.ts +104 -104
  273. 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
  }