@blackcode_sa/metaestetics-api 1.11.1 → 1.11.2

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 (36) hide show
  1. package/dist/admin/index.d.mts +324 -330
  2. package/dist/admin/index.d.ts +324 -330
  3. package/dist/backoffice/index.d.mts +67 -283
  4. package/dist/backoffice/index.d.ts +67 -283
  5. package/dist/backoffice/index.js +6 -114
  6. package/dist/backoffice/index.mjs +6 -112
  7. package/dist/index.d.mts +3037 -3100
  8. package/dist/index.d.ts +3037 -3100
  9. package/dist/index.js +129 -379
  10. package/dist/index.mjs +130 -379
  11. package/package.json +1 -1
  12. package/src/backoffice/expo-safe/index.ts +0 -2
  13. package/src/backoffice/services/__tests__/brand.service.test.ts +196 -0
  14. package/src/backoffice/services/__tests__/category.service.test.ts +201 -0
  15. package/src/backoffice/services/__tests__/product.service.test.ts +358 -0
  16. package/src/backoffice/services/__tests__/requirement.service.test.ts +226 -0
  17. package/src/backoffice/services/__tests__/subcategory.service.test.ts +181 -0
  18. package/src/backoffice/services/__tests__/technology.service.test.ts +1097 -0
  19. package/src/backoffice/services/technology.service.ts +10 -122
  20. package/src/backoffice/types/index.ts +0 -1
  21. package/src/backoffice/types/product.types.ts +1 -3
  22. package/src/backoffice/types/technology.types.ts +4 -4
  23. package/src/backoffice/validations/schemas.ts +9 -35
  24. package/src/services/appointment/appointment.service.ts +5 -0
  25. package/src/services/appointment/utils/appointment.utils.ts +113 -124
  26. package/src/services/procedure/procedure.service.ts +234 -434
  27. package/src/types/appointment/index.ts +37 -43
  28. package/src/types/clinic/index.ts +6 -1
  29. package/src/types/patient/medical-info.types.ts +3 -3
  30. package/src/types/procedure/index.ts +17 -20
  31. package/src/validations/appointment.schema.ts +118 -170
  32. package/src/validations/clinic.schema.ts +6 -1
  33. package/src/validations/patient/medical-info.schema.ts +2 -7
  34. package/src/backoffice/services/README.md +0 -40
  35. package/src/backoffice/services/constants.service.ts +0 -268
  36. package/src/backoffice/types/admin-constants.types.ts +0 -69
@@ -1,15 +1,8 @@
1
- import { z } from "zod";
2
- import {
3
- AppointmentStatus,
4
- PaymentStatus,
5
- MediaType,
6
- } from "../types/appointment";
7
- import { filledDocumentStatusSchema } from "./documentation-templates.schema";
8
- import {
9
- Currency,
10
- PricingMeasure,
11
- } from "../backoffice/types/static/pricing.types";
12
- import { mediaResourceSchema } from "./media.schema";
1
+ import { z } from 'zod';
2
+ import { AppointmentStatus, PaymentStatus, MediaType } from '../types/appointment';
3
+ import { filledDocumentStatusSchema } from './documentation-templates.schema';
4
+ import { Currency, PricingMeasure } from '../backoffice/types/static/pricing.types';
5
+ import { mediaResourceSchema } from './media.schema';
13
6
 
14
7
  // Define common constants locally if not available from common.schema.ts
15
8
  const MIN_STRING_LENGTH = 1;
@@ -25,9 +18,9 @@ export const mediaTypeSchema = z.nativeEnum(MediaType);
25
18
  // --- Schemas for Nested Objects from types/appointment/index.ts ---
26
19
 
27
20
  export const appointmentMediaItemSchema = z.object({
28
- id: z.string().min(MIN_STRING_LENGTH, "Media item ID is required"),
21
+ id: z.string().min(MIN_STRING_LENGTH, 'Media item ID is required'),
29
22
  type: mediaTypeSchema,
30
- url: z.string().url("Media URL must be a valid URL"),
23
+ url: z.string().url('Media URL must be a valid URL'),
31
24
  fileName: z.string().optional(),
32
25
  uploadedAt: z
33
26
  .any()
@@ -36,18 +29,13 @@ export const appointmentMediaItemSchema = z.object({
36
29
  val instanceof Date ||
37
30
  val?._seconds !== undefined ||
38
31
  val?.seconds !== undefined ||
39
- typeof val === "number" ||
40
- typeof val === "string" ||
41
- (val && typeof val.toMillis === "function"),
42
- "uploadedAt must be a valid timestamp or Date object"
32
+ typeof val === 'number' ||
33
+ typeof val === 'string' ||
34
+ (val && typeof val.toMillis === 'function'),
35
+ 'uploadedAt must be a valid timestamp or Date object',
43
36
  ),
44
- uploadedBy: z
45
- .string()
46
- .min(MIN_STRING_LENGTH, "Uploaded by user ID is required"),
47
- description: z
48
- .string()
49
- .max(MAX_STRING_LENGTH, "Description too long")
50
- .optional(),
37
+ uploadedBy: z.string().min(MIN_STRING_LENGTH, 'Uploaded by user ID is required'),
38
+ description: z.string().max(MAX_STRING_LENGTH, 'Description too long').optional(),
51
39
  });
52
40
 
53
41
  export const procedureExtendedInfoSchema = z.object({
@@ -70,17 +58,14 @@ export const procedureExtendedInfoSchema = z.object({
70
58
  });
71
59
 
72
60
  export const linkedFormInfoSchema = z.object({
73
- formId: z.string().min(MIN_STRING_LENGTH, "Form ID is required"),
74
- templateId: z.string().min(MIN_STRING_LENGTH, "Template ID is required"),
75
- templateVersion: z
76
- .number()
77
- .int()
78
- .positive("Template version must be a positive integer"),
79
- title: z.string().min(MIN_STRING_LENGTH, "Form title is required"),
61
+ formId: z.string().min(MIN_STRING_LENGTH, 'Form ID is required'),
62
+ templateId: z.string().min(MIN_STRING_LENGTH, 'Template ID is required'),
63
+ templateVersion: z.number().int().positive('Template version must be a positive integer'),
64
+ title: z.string().min(MIN_STRING_LENGTH, 'Form title is required'),
80
65
  isUserForm: z.boolean(),
81
66
  isRequired: z.boolean().optional(),
82
67
  status: filledDocumentStatusSchema,
83
- path: z.string().min(MIN_STRING_LENGTH, "Form path is required"),
68
+ path: z.string().min(MIN_STRING_LENGTH, 'Form path is required'),
84
69
  submittedAt: z
85
70
  .any()
86
71
  .refine(
@@ -89,10 +74,10 @@ export const linkedFormInfoSchema = z.object({
89
74
  val instanceof Date ||
90
75
  val?._seconds !== undefined ||
91
76
  val?.seconds !== undefined ||
92
- typeof val === "number" ||
93
- typeof val === "string" ||
94
- (val && typeof val.toMillis === "function"),
95
- "submittedAt must be a valid timestamp or Date object"
77
+ typeof val === 'number' ||
78
+ typeof val === 'string' ||
79
+ (val && typeof val.toMillis === 'function'),
80
+ 'submittedAt must be a valid timestamp or Date object',
96
81
  )
97
82
  .optional(),
98
83
  completedAt: z
@@ -103,21 +88,18 @@ export const linkedFormInfoSchema = z.object({
103
88
  val instanceof Date ||
104
89
  val?._seconds !== undefined ||
105
90
  val?.seconds !== undefined ||
106
- typeof val === "number" ||
107
- typeof val === "string" ||
108
- (val && typeof val.toMillis === "function"),
109
- "completedAt must be a valid timestamp or Date object"
91
+ typeof val === 'number' ||
92
+ typeof val === 'string' ||
93
+ (val && typeof val.toMillis === 'function'),
94
+ 'completedAt must be a valid timestamp or Date object',
110
95
  )
111
96
  .optional(),
112
97
  });
113
98
 
114
99
  export const patientReviewInfoSchema = z.object({
115
- reviewId: z.string().min(MIN_STRING_LENGTH, "Review ID is required"),
116
- rating: z.number().min(1).max(5, "Rating must be between 1 and 5"),
117
- comment: z
118
- .string()
119
- .max(MAX_STRING_LENGTH_LONG, "Comment too long")
120
- .optional(),
100
+ reviewId: z.string().min(MIN_STRING_LENGTH, 'Review ID is required'),
101
+ rating: z.number().min(1).max(5, 'Rating must be between 1 and 5'),
102
+ comment: z.string().max(MAX_STRING_LENGTH_LONG, 'Comment too long').optional(),
121
103
  reviewedAt: z
122
104
  .any()
123
105
  .refine(
@@ -125,15 +107,15 @@ export const patientReviewInfoSchema = z.object({
125
107
  val instanceof Date ||
126
108
  val?._seconds !== undefined ||
127
109
  val?.seconds !== undefined ||
128
- typeof val === "number" ||
129
- typeof val === "string" ||
130
- (val && typeof val.toMillis === "function"),
131
- "reviewedAt must be a valid timestamp or Date object"
110
+ typeof val === 'number' ||
111
+ typeof val === 'string' ||
112
+ (val && typeof val.toMillis === 'function'),
113
+ 'reviewedAt must be a valid timestamp or Date object',
132
114
  ),
133
115
  });
134
116
 
135
117
  export const finalizedDetailsSchema = z.object({
136
- by: z.string().min(MIN_STRING_LENGTH, "Finalized by user ID is required"),
118
+ by: z.string().min(MIN_STRING_LENGTH, 'Finalized by user ID is required'),
137
119
  at: z
138
120
  .any()
139
121
  .refine(
@@ -141,15 +123,12 @@ export const finalizedDetailsSchema = z.object({
141
123
  val instanceof Date ||
142
124
  val?._seconds !== undefined ||
143
125
  val?.seconds !== undefined ||
144
- typeof val === "number" ||
145
- typeof val === "string" ||
146
- (val && typeof val.toMillis === "function"),
147
- "Finalized at must be a valid timestamp or Date object"
126
+ typeof val === 'number' ||
127
+ typeof val === 'string' ||
128
+ (val && typeof val.toMillis === 'function'),
129
+ 'Finalized at must be a valid timestamp or Date object',
148
130
  ),
149
- notes: z
150
- .string()
151
- .max(MAX_STRING_LENGTH_LONG, "Finalization notes too long")
152
- .optional(),
131
+ notes: z.string().max(MAX_STRING_LENGTH_LONG, 'Finalization notes too long').optional(),
153
132
  });
154
133
 
155
134
  /**
@@ -158,32 +137,34 @@ export const finalizedDetailsSchema = z.object({
158
137
  export const beforeAfterPerZoneSchema = z.object({
159
138
  before: mediaResourceSchema.nullable(),
160
139
  after: mediaResourceSchema.nullable(),
161
- note: z.string().nullable(),
140
+ afterNote: z.string().nullable().optional(),
141
+ beforeNote: z.string().nullable().optional(),
162
142
  });
163
143
 
164
144
  /**
165
145
  * Schema for billing information per zone
166
146
  */
167
147
  export const billingPerZoneSchema = z.object({
168
- Product: z.string().min(MIN_STRING_LENGTH, "Product name is required"),
148
+ Product: z.string().min(MIN_STRING_LENGTH, 'Product name is required'),
169
149
  ProductId: z.string().nullable(),
170
- Quantity: z.number().min(0, "Quantity must be non-negative"),
150
+ Quantity: z.number().min(0, 'Quantity must be non-negative'),
171
151
  UnitOfMeasurement: z.nativeEnum(PricingMeasure),
172
- UnitPrice: z.number().min(0, "Unit price must be non-negative"),
152
+ UnitPrice: z.number().min(0, 'Unit price must be non-negative'),
173
153
  UnitCurency: z.nativeEnum(Currency),
174
- Subtotal: z.number().min(0, "Subtotal must be non-negative"),
154
+ Subtotal: z.number().min(0, 'Subtotal must be non-negative'),
175
155
  Note: z.string().nullable(),
156
+ IonNumber: z.string().nullable(),
176
157
  });
177
158
 
178
159
  /**
179
160
  * Schema for final billing calculations of the appointment
180
161
  */
181
162
  export const finalBillingSchema = z.object({
182
- subtotalAll: z.number().min(0, "Subtotal all must be non-negative"),
183
- taxRate: z.number().min(0).max(1, "Tax rate must be between 0 and 1"),
184
- taxPrice: z.number().min(0, "Tax price must be non-negative"),
185
- finalPrice: z.number().min(0, "Final price must be non-negative"),
186
- finalQuantity: z.number().min(0, "Final quantity must be non-negative"),
163
+ subtotalAll: z.number().min(0, 'Subtotal all must be non-negative'),
164
+ taxRate: z.number().min(0).max(1, 'Tax rate must be between 0 and 1'),
165
+ taxPrice: z.number().min(0, 'Tax price must be non-negative'),
166
+ finalPrice: z.number().min(0, 'Final price must be non-negative'),
167
+ finalQuantity: z.number().min(0, 'Final quantity must be non-negative'),
187
168
  currency: z.nativeEnum(Currency),
188
169
  unitOfMeasurement: z.nativeEnum(PricingMeasure),
189
170
  });
@@ -205,14 +186,10 @@ export const appointmentMetadataSchema = z.object({
205
186
  */
206
187
  export const createAppointmentSchema = z
207
188
  .object({
208
- clinicBranchId: z
209
- .string()
210
- .min(MIN_STRING_LENGTH, "Clinic branch ID is required"),
211
- practitionerId: z
212
- .string()
213
- .min(MIN_STRING_LENGTH, "Practitioner ID is required"),
214
- patientId: z.string().min(MIN_STRING_LENGTH, "Patient ID is required"),
215
- procedureId: z.string().min(MIN_STRING_LENGTH, "Procedure ID is required"),
189
+ clinicBranchId: z.string().min(MIN_STRING_LENGTH, 'Clinic branch ID is required'),
190
+ practitionerId: z.string().min(MIN_STRING_LENGTH, 'Practitioner ID is required'),
191
+ patientId: z.string().min(MIN_STRING_LENGTH, 'Patient ID is required'),
192
+ procedureId: z.string().min(MIN_STRING_LENGTH, 'Procedure ID is required'),
216
193
  appointmentStartTime: z
217
194
  .any()
218
195
  .refine(
@@ -220,10 +197,10 @@ export const createAppointmentSchema = z
220
197
  val instanceof Date ||
221
198
  val?._seconds !== undefined ||
222
199
  val?.seconds !== undefined ||
223
- typeof val === "number" ||
224
- typeof val === "string" ||
225
- (val && typeof val.toMillis === "function"),
226
- "Appointment start time must be a valid timestamp or Date object"
200
+ typeof val === 'number' ||
201
+ typeof val === 'string' ||
202
+ (val && typeof val.toMillis === 'function'),
203
+ 'Appointment start time must be a valid timestamp or Date object',
227
204
  ),
228
205
  appointmentEndTime: z
229
206
  .any()
@@ -232,27 +209,21 @@ export const createAppointmentSchema = z
232
209
  val instanceof Date ||
233
210
  val?._seconds !== undefined ||
234
211
  val?.seconds !== undefined ||
235
- typeof val === "number" ||
236
- typeof val === "string" ||
237
- (val && typeof val.toMillis === "function"),
238
- "Appointment end time must be a valid timestamp or Date object"
212
+ typeof val === 'number' ||
213
+ typeof val === 'string' ||
214
+ (val && typeof val.toMillis === 'function'),
215
+ 'Appointment end time must be a valid timestamp or Date object',
239
216
  ),
240
- cost: z.number().min(0, "Cost must be a non-negative number"),
241
- currency: z.string().min(1, "Currency is required"),
242
- patientNotes: z
243
- .string()
244
- .max(MAX_STRING_LENGTH, "Patient notes too long")
245
- .nullable()
246
- .optional(),
217
+ cost: z.number().min(0, 'Cost must be a non-negative number'),
218
+ currency: z.string().min(1, 'Currency is required'),
219
+ patientNotes: z.string().max(MAX_STRING_LENGTH, 'Patient notes too long').nullable().optional(),
247
220
  initialStatus: appointmentStatusSchema,
248
- initialPaymentStatus: paymentStatusSchema
249
- .optional()
250
- .default(PaymentStatus.UNPAID),
251
- clinic_tz: z.string().min(1, "Timezone is required"),
221
+ initialPaymentStatus: paymentStatusSchema.optional().default(PaymentStatus.UNPAID),
222
+ clinic_tz: z.string().min(1, 'Timezone is required'),
252
223
  })
253
224
  .refine((data) => data.appointmentEndTime > data.appointmentStartTime, {
254
- message: "Appointment end time must be after start time",
255
- path: ["appointmentEndTime"],
225
+ message: 'Appointment end time must be after start time',
226
+ path: ['appointmentEndTime'],
256
227
  });
257
228
 
258
229
  /**
@@ -268,30 +239,24 @@ export const updateAppointmentSchema = z
268
239
  actualDurationMinutes: z
269
240
  .number()
270
241
  .int()
271
- .positive("Duration must be a positive integer")
242
+ .positive('Duration must be a positive integer')
272
243
  .optional(),
273
244
  cancellationReason: z
274
245
  .string()
275
- .max(MAX_STRING_LENGTH, "Cancellation reason too long")
246
+ .max(MAX_STRING_LENGTH, 'Cancellation reason too long')
276
247
  .nullable()
277
248
  .optional(),
278
- canceledBy: z
279
- .enum(["patient", "clinic", "practitioner", "system"])
280
- .optional(),
249
+ canceledBy: z.enum(['patient', 'clinic', 'practitioner', 'system']).optional(),
281
250
  internalNotes: z
282
251
  .string()
283
- .max(MAX_STRING_LENGTH_LONG, "Internal notes too long")
252
+ .max(MAX_STRING_LENGTH_LONG, 'Internal notes too long')
284
253
  .nullable()
285
254
  .optional(),
286
255
  patientNotes: z.any().optional().nullable(),
287
256
  paymentStatus: paymentStatusSchema.optional(),
288
257
  paymentTransactionId: z.any().optional().nullable(),
289
- completedPreRequirements: z
290
- .union([z.array(z.string()), z.any()])
291
- .optional(),
292
- completedPostRequirements: z
293
- .union([z.array(z.string()), z.any()])
294
- .optional(),
258
+ completedPreRequirements: z.union([z.array(z.string()), z.any()]).optional(),
259
+ completedPostRequirements: z.union([z.array(z.string()), z.any()]).optional(),
295
260
  linkedFormIds: z.union([z.array(z.string()), z.any()]).optional(),
296
261
  pendingUserFormsIds: z.union([z.array(z.string()), z.any()]).optional(),
297
262
  appointmentStartTime: z
@@ -302,10 +267,10 @@ export const updateAppointmentSchema = z
302
267
  val instanceof Date ||
303
268
  val?._seconds !== undefined ||
304
269
  val?.seconds !== undefined ||
305
- typeof val === "number" ||
306
- typeof val === "string" ||
307
- (val && typeof val.toMillis === "function"),
308
- "Appointment start time must be a valid timestamp or Date object"
270
+ typeof val === 'number' ||
271
+ typeof val === 'string' ||
272
+ (val && typeof val.toMillis === 'function'),
273
+ 'Appointment start time must be a valid timestamp or Date object',
309
274
  )
310
275
  .optional(),
311
276
  appointmentEndTime: z
@@ -316,10 +281,10 @@ export const updateAppointmentSchema = z
316
281
  val instanceof Date ||
317
282
  val?._seconds !== undefined ||
318
283
  val?.seconds !== undefined ||
319
- typeof val === "number" ||
320
- typeof val === "string" ||
321
- (val && typeof val.toMillis === "function"),
322
- "Appointment end time must be a valid timestamp or Date object"
284
+ typeof val === 'number' ||
285
+ typeof val === 'string' ||
286
+ (val && typeof val.toMillis === 'function'),
287
+ 'Appointment end time must be a valid timestamp or Date object',
323
288
  )
324
289
  .optional(),
325
290
  calendarEventId: z.string().min(MIN_STRING_LENGTH).optional(),
@@ -327,21 +292,10 @@ export const updateAppointmentSchema = z
327
292
  clinicBranchId: z.string().min(MIN_STRING_LENGTH).optional(),
328
293
  practitionerId: z.string().min(MIN_STRING_LENGTH).optional(),
329
294
  clinic_tz: z.string().min(MIN_STRING_LENGTH).optional(),
330
- linkedForms: z
331
- .union([z.array(linkedFormInfoSchema).max(MAX_ARRAY_LENGTH), z.any()])
332
- .optional(),
333
- media: z
334
- .union([
335
- z.array(appointmentMediaItemSchema).max(MAX_ARRAY_LENGTH),
336
- z.any(),
337
- ])
338
- .optional(),
339
- reviewInfo: z
340
- .union([patientReviewInfoSchema.nullable(), z.any()])
341
- .optional(),
342
- finalizedDetails: z
343
- .union([finalizedDetailsSchema.nullable(), z.any()])
344
- .optional(),
295
+ linkedForms: z.union([z.array(linkedFormInfoSchema).max(MAX_ARRAY_LENGTH), z.any()]).optional(),
296
+ media: z.union([z.array(appointmentMediaItemSchema).max(MAX_ARRAY_LENGTH), z.any()]).optional(),
297
+ reviewInfo: z.union([patientReviewInfoSchema.nullable(), z.any()]).optional(),
298
+ finalizedDetails: z.union([finalizedDetailsSchema.nullable(), z.any()]).optional(),
345
299
  isArchived: z.boolean().optional(),
346
300
  updatedAt: z.any().optional(),
347
301
  metadata: appointmentMetadataSchema.optional(),
@@ -359,9 +313,9 @@ export const updateAppointmentSchema = z
359
313
  },
360
314
  {
361
315
  message:
362
- "Cancellation reason and canceled by must be provided when canceling an appointment with patient or clinic origin.",
363
- path: ["status"],
364
- }
316
+ 'Cancellation reason and canceled by must be provided when canceling an appointment with patient or clinic origin.',
317
+ path: ['status'],
318
+ },
365
319
  )
366
320
  .refine(
367
321
  (data) => {
@@ -371,10 +325,9 @@ export const updateAppointmentSchema = z
371
325
  return true;
372
326
  },
373
327
  {
374
- message:
375
- "Appointment end time must be after start time if both are provided",
376
- path: ["appointmentEndTime"],
377
- }
328
+ message: 'Appointment end time must be after start time if both are provided',
329
+ path: ['appointmentEndTime'],
330
+ },
378
331
  );
379
332
 
380
333
  /**
@@ -393,10 +346,10 @@ export const searchAppointmentsSchema = z
393
346
  val instanceof Date ||
394
347
  val?._seconds !== undefined ||
395
348
  val?.seconds !== undefined ||
396
- typeof val === "number" ||
397
- typeof val === "string" ||
398
- (val && typeof val.toMillis === "function"),
399
- "Start date must be a valid timestamp or Date object"
349
+ typeof val === 'number' ||
350
+ typeof val === 'string' ||
351
+ (val && typeof val.toMillis === 'function'),
352
+ 'Start date must be a valid timestamp or Date object',
400
353
  )
401
354
  .optional(),
402
355
  endDate: z
@@ -407,17 +360,14 @@ export const searchAppointmentsSchema = z
407
360
  val instanceof Date ||
408
361
  val?._seconds !== undefined ||
409
362
  val?.seconds !== undefined ||
410
- typeof val === "number" ||
411
- typeof val === "string" ||
412
- (val && typeof val.toMillis === "function"),
413
- "End date must be a valid timestamp or Date object"
363
+ typeof val === 'number' ||
364
+ typeof val === 'string' ||
365
+ (val && typeof val.toMillis === 'function'),
366
+ 'End date must be a valid timestamp or Date object',
414
367
  )
415
368
  .optional(),
416
369
  status: z
417
- .union([
418
- appointmentStatusSchema,
419
- z.array(appointmentStatusSchema).nonempty(),
420
- ])
370
+ .union([appointmentStatusSchema, z.array(appointmentStatusSchema).nonempty()])
421
371
  .optional(),
422
372
  limit: z.number().positive().int().optional().default(20),
423
373
  startAfter: z.any().optional(),
@@ -431,9 +381,9 @@ export const searchAppointmentsSchema = z
431
381
  },
432
382
  {
433
383
  message:
434
- "At least one of patientId, practitionerId, or clinicBranchId must be provided if no date or status filters are set.",
435
- path: ["patientId"],
436
- }
384
+ 'At least one of patientId, practitionerId, or clinicBranchId must be provided if no date or status filters are set.',
385
+ path: ['patientId'],
386
+ },
437
387
  )
438
388
  .refine(
439
389
  (data) => {
@@ -443,18 +393,16 @@ export const searchAppointmentsSchema = z
443
393
  return true;
444
394
  },
445
395
  {
446
- message: "End date must be after or the same as start date",
447
- path: ["endDate"],
448
- }
396
+ message: 'End date must be after or the same as start date',
397
+ path: ['endDate'],
398
+ },
449
399
  );
450
400
 
451
401
  /**
452
402
  * Schema for validating appointment reschedule data
453
403
  */
454
404
  export const rescheduleAppointmentSchema = z.object({
455
- appointmentId: z
456
- .string()
457
- .min(MIN_STRING_LENGTH, "Appointment ID is required"),
405
+ appointmentId: z.string().min(MIN_STRING_LENGTH, 'Appointment ID is required'),
458
406
  newStartTime: z
459
407
  .any()
460
408
  .refine(
@@ -462,10 +410,10 @@ export const rescheduleAppointmentSchema = z.object({
462
410
  val instanceof Date ||
463
411
  val?._seconds !== undefined ||
464
412
  val?.seconds !== undefined ||
465
- typeof val === "number" ||
466
- typeof val === "string" ||
467
- (val && typeof val.toMillis === "function"),
468
- "New start time must be a valid timestamp, Date object, number, or string"
413
+ typeof val === 'number' ||
414
+ typeof val === 'string' ||
415
+ (val && typeof val.toMillis === 'function'),
416
+ 'New start time must be a valid timestamp, Date object, number, or string',
469
417
  ),
470
418
  newEndTime: z
471
419
  .any()
@@ -474,9 +422,9 @@ export const rescheduleAppointmentSchema = z.object({
474
422
  val instanceof Date ||
475
423
  val?._seconds !== undefined ||
476
424
  val?.seconds !== undefined ||
477
- typeof val === "number" ||
478
- typeof val === "string" ||
479
- (val && typeof val.toMillis === "function"),
480
- "New end time must be a valid timestamp, Date object, number, or string"
425
+ typeof val === 'number' ||
426
+ typeof val === 'string' ||
427
+ (val && typeof val.toMillis === 'function'),
428
+ 'New end time must be a valid timestamp, Date object, number, or string',
481
429
  ),
482
430
  });
@@ -7,7 +7,12 @@ import {
7
7
  PracticeType,
8
8
  Language,
9
9
  } from "../types/clinic";
10
-
10
+ import { ProcedureFamily } from "../backoffice/types/static/procedure-family.types";
11
+ import { TreatmentBenefit } from "../backoffice/types/static/treatment-benefit.types";
12
+ import {
13
+ Currency,
14
+ PricingMeasure,
15
+ } from "../backoffice/types/static/pricing.types";
11
16
  import { clinicReviewInfoSchema } from "./reviews.schema";
12
17
  import {
13
18
  procedureSummaryInfoSchema,
@@ -7,6 +7,7 @@ import {
7
7
  CosmeticAllergySubtype,
8
8
  } from "../../types/patient/allergies";
9
9
  import { BlockingCondition } from "../../backoffice/types/static/blocking-condition.types";
10
+ import { Contraindication } from "../../backoffice/types/static/contraindication.types";
10
11
  import { timestampSchema } from "../common.schema";
11
12
 
12
13
  export const allergySubtypeSchema = z.union([
@@ -49,14 +50,8 @@ export const blockingConditionSchema = z.object({
49
50
  isActive: z.boolean(),
50
51
  });
51
52
 
52
- export const contraindicationDynamicSchema = z.object({
53
- id: z.string(),
54
- name: z.string(),
55
- description: z.string().optional(),
56
- });
57
-
58
53
  export const contraindicationSchema = z.object({
59
- condition: contraindicationDynamicSchema,
54
+ condition: z.nativeEnum(Contraindication),
60
55
  lastOccurrence: timestampSchema,
61
56
  frequency: z.enum(["rare", "occasional", "frequent"]),
62
57
  notes: z.string().optional().nullable(),
@@ -1,40 +0,0 @@
1
- # Backoffice Services
2
-
3
- This directory contains services used by the backoffice application.
4
-
5
- ## Services
6
-
7
- ### `CategoryService`
8
-
9
- Manages procedure categories. Categories are the first level of organization after procedure family (aesthetics/surgery).
10
-
11
- - **`create(category)`**: Creates a new category.
12
- - **`getAll()`**: Retrieves all active categories.
13
- - **`getAllByFamily(family)`**: Retrieves all active categories for a specific procedure family.
14
- - **`update(id, category)`**: Updates an existing category.
15
- - **`delete(id)`**: Soft deletes a category.
16
- - **`getById(id)`**: Retrieves a category by its ID.
17
-
18
- ### `ProductService`
19
-
20
- Manages products, which are sub-items of a `Technology`.
21
-
22
- - **`create(technologyId, brandId, product)`**: Creates a new product under a technology.
23
- - **`getAllByTechnology(technologyId)`**: Retrieves all products for a technology.
24
- - **`getAllByBrand(brandId)`**: Retrieves all products for a brand.
25
- - **`update(technologyId, productId, product)`**: Updates a product.
26
- - **`delete(technologyId, productId)`**: Soft deletes a product.
27
- - **`getById(technologyId, productId)`**: Retrieves a product by its ID.
28
-
29
- ### `ConstantsService`
30
-
31
- Manages administrative constants like treatment benefits and contraindications.
32
-
33
- - **`getTreatmentBenefits()`**: Retrieves all treatment benefits.
34
- - **`addTreatmentBenefit(benefit)`**: Adds a new treatment benefit.
35
- - **`updateTreatmentBenefit(benefit)`**: Updates an existing treatment benefit.
36
- - **`deleteTreatmentBenefit(benefitId)`**: Deletes a treatment benefit.
37
- - **`getContraindications()`**: Retrieves all contraindications.
38
- - **`addContraindication(contraindication)`**: Adds a new contraindication.
39
- - **`updateContraindication(contraindication)`**: Updates an existing contraindication.
40
- - **`deleteContraindication(contraindicationId)`**: Deletes a contraindication.