@blackcode_sa/metaestetics-api 1.7.38 → 1.7.40

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.
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/validations/appointment.schema.ts
2
- import { z as z2 } from "zod";
2
+ import { z as z3 } from "zod";
3
3
 
4
4
  // src/types/appointment/index.ts
5
5
  var AppointmentStatus = /* @__PURE__ */ ((AppointmentStatus2) => {
@@ -267,140 +267,197 @@ var updateFilledDocumentDataSchema = z.object({
267
267
  status: filledDocumentStatusSchema.optional()
268
268
  });
269
269
 
270
+ // src/backoffice/types/static/pricing.types.ts
271
+ var PricingMeasure = /* @__PURE__ */ ((PricingMeasure3) => {
272
+ PricingMeasure3["PER_ML"] = "per_ml";
273
+ PricingMeasure3["PER_ZONE"] = "per_zone";
274
+ PricingMeasure3["PER_AREA"] = "per_area";
275
+ PricingMeasure3["PER_SESSION"] = "per_session";
276
+ PricingMeasure3["PER_TREATMENT"] = "per_treatment";
277
+ PricingMeasure3["PER_PACKAGE"] = "per_package";
278
+ return PricingMeasure3;
279
+ })(PricingMeasure || {});
280
+ var Currency = /* @__PURE__ */ ((Currency2) => {
281
+ Currency2["EUR"] = "EUR";
282
+ Currency2["USD"] = "USD";
283
+ Currency2["GBP"] = "GBP";
284
+ Currency2["CHF"] = "CHF";
285
+ Currency2["AUD"] = "AUD";
286
+ return Currency2;
287
+ })(Currency || {});
288
+
289
+ // src/validations/media.schema.ts
290
+ import { z as z2 } from "zod";
291
+ var mediaResourceSchema = z2.union([
292
+ z2.string().url(),
293
+ z2.instanceof(File),
294
+ z2.instanceof(Blob)
295
+ ]);
296
+
270
297
  // src/validations/appointment.schema.ts
271
298
  var MIN_STRING_LENGTH = 1;
272
299
  var MAX_STRING_LENGTH = 1024;
273
300
  var MAX_STRING_LENGTH_LONG = 4096;
274
301
  var MAX_ARRAY_LENGTH = 100;
275
- var appointmentStatusSchema = z2.nativeEnum(AppointmentStatus);
276
- var paymentStatusSchema = z2.nativeEnum(PaymentStatus);
277
- var mediaTypeSchema = z2.nativeEnum(MediaType);
278
- var appointmentMediaItemSchema = z2.object({
279
- id: z2.string().min(MIN_STRING_LENGTH, "Media item ID is required"),
302
+ var appointmentStatusSchema = z3.nativeEnum(AppointmentStatus);
303
+ var paymentStatusSchema = z3.nativeEnum(PaymentStatus);
304
+ var mediaTypeSchema = z3.nativeEnum(MediaType);
305
+ var appointmentMediaItemSchema = z3.object({
306
+ id: z3.string().min(MIN_STRING_LENGTH, "Media item ID is required"),
280
307
  type: mediaTypeSchema,
281
- url: z2.string().url("Media URL must be a valid URL"),
282
- fileName: z2.string().optional(),
283
- uploadedAt: z2.any().refine(
308
+ url: z3.string().url("Media URL must be a valid URL"),
309
+ fileName: z3.string().optional(),
310
+ uploadedAt: z3.any().refine(
284
311
  (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
285
312
  "uploadedAt must be a valid timestamp or Date object"
286
313
  ),
287
- uploadedBy: z2.string().min(MIN_STRING_LENGTH, "Uploaded by user ID is required"),
288
- description: z2.string().max(MAX_STRING_LENGTH, "Description too long").optional()
314
+ uploadedBy: z3.string().min(MIN_STRING_LENGTH, "Uploaded by user ID is required"),
315
+ description: z3.string().max(MAX_STRING_LENGTH, "Description too long").optional()
289
316
  });
290
- var procedureExtendedInfoSchema = z2.object({
291
- id: z2.string().min(MIN_STRING_LENGTH),
292
- name: z2.string().min(MIN_STRING_LENGTH),
293
- description: z2.string(),
294
- cost: z2.number().min(0),
295
- duration: z2.number().min(0),
296
- procedureFamily: z2.any(),
297
- procedureCategoryId: z2.string(),
298
- procedureCategoryName: z2.string(),
299
- procedureSubCategoryId: z2.string(),
300
- procedureSubCategoryName: z2.string(),
301
- procedureTechnologyId: z2.string(),
302
- procedureTechnologyName: z2.string(),
303
- procedureProductBrandId: z2.string(),
304
- procedureProductBrandName: z2.string(),
305
- procedureProductId: z2.string(),
306
- procedureProductName: z2.string()
317
+ var procedureExtendedInfoSchema = z3.object({
318
+ id: z3.string().min(MIN_STRING_LENGTH),
319
+ name: z3.string().min(MIN_STRING_LENGTH),
320
+ description: z3.string(),
321
+ cost: z3.number().min(0),
322
+ duration: z3.number().min(0),
323
+ procedureFamily: z3.any(),
324
+ procedureCategoryId: z3.string(),
325
+ procedureCategoryName: z3.string(),
326
+ procedureSubCategoryId: z3.string(),
327
+ procedureSubCategoryName: z3.string(),
328
+ procedureTechnologyId: z3.string(),
329
+ procedureTechnologyName: z3.string(),
330
+ procedureProductBrandId: z3.string(),
331
+ procedureProductBrandName: z3.string(),
332
+ procedureProductId: z3.string(),
333
+ procedureProductName: z3.string()
307
334
  });
308
- var linkedFormInfoSchema = z2.object({
309
- formId: z2.string().min(MIN_STRING_LENGTH, "Form ID is required"),
310
- templateId: z2.string().min(MIN_STRING_LENGTH, "Template ID is required"),
311
- templateVersion: z2.number().int().positive("Template version must be a positive integer"),
312
- title: z2.string().min(MIN_STRING_LENGTH, "Form title is required"),
313
- isUserForm: z2.boolean(),
314
- isRequired: z2.boolean().optional(),
335
+ var linkedFormInfoSchema = z3.object({
336
+ formId: z3.string().min(MIN_STRING_LENGTH, "Form ID is required"),
337
+ templateId: z3.string().min(MIN_STRING_LENGTH, "Template ID is required"),
338
+ templateVersion: z3.number().int().positive("Template version must be a positive integer"),
339
+ title: z3.string().min(MIN_STRING_LENGTH, "Form title is required"),
340
+ isUserForm: z3.boolean(),
341
+ isRequired: z3.boolean().optional(),
315
342
  status: filledDocumentStatusSchema,
316
- path: z2.string().min(MIN_STRING_LENGTH, "Form path is required"),
317
- submittedAt: z2.any().refine(
343
+ path: z3.string().min(MIN_STRING_LENGTH, "Form path is required"),
344
+ submittedAt: z3.any().refine(
318
345
  (val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
319
346
  "submittedAt must be a valid timestamp or Date object"
320
347
  ).optional(),
321
- completedAt: z2.any().refine(
348
+ completedAt: z3.any().refine(
322
349
  (val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
323
350
  "completedAt must be a valid timestamp or Date object"
324
351
  ).optional()
325
352
  });
326
- var patientReviewInfoSchema = z2.object({
327
- reviewId: z2.string().min(MIN_STRING_LENGTH, "Review ID is required"),
328
- rating: z2.number().min(1).max(5, "Rating must be between 1 and 5"),
329
- comment: z2.string().max(MAX_STRING_LENGTH_LONG, "Comment too long").optional(),
330
- reviewedAt: z2.any().refine(
353
+ var patientReviewInfoSchema = z3.object({
354
+ reviewId: z3.string().min(MIN_STRING_LENGTH, "Review ID is required"),
355
+ rating: z3.number().min(1).max(5, "Rating must be between 1 and 5"),
356
+ comment: z3.string().max(MAX_STRING_LENGTH_LONG, "Comment too long").optional(),
357
+ reviewedAt: z3.any().refine(
331
358
  (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
332
359
  "reviewedAt must be a valid timestamp or Date object"
333
360
  )
334
361
  });
335
- var finalizedDetailsSchema = z2.object({
336
- by: z2.string().min(MIN_STRING_LENGTH, "Finalized by user ID is required"),
337
- at: z2.any().refine(
362
+ var finalizedDetailsSchema = z3.object({
363
+ by: z3.string().min(MIN_STRING_LENGTH, "Finalized by user ID is required"),
364
+ at: z3.any().refine(
338
365
  (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
339
366
  "Finalized at must be a valid timestamp or Date object"
340
367
  ),
341
- notes: z2.string().max(MAX_STRING_LENGTH_LONG, "Finalization notes too long").optional()
368
+ notes: z3.string().max(MAX_STRING_LENGTH_LONG, "Finalization notes too long").optional()
369
+ });
370
+ var beforeAfterPerZoneSchema = z3.object({
371
+ before: mediaResourceSchema.nullable(),
372
+ after: mediaResourceSchema.nullable(),
373
+ note: z3.string().nullable()
374
+ });
375
+ var billingPerZoneSchema = z3.object({
376
+ Product: z3.string().min(MIN_STRING_LENGTH, "Product name is required"),
377
+ ProductId: z3.string().nullable(),
378
+ Quantity: z3.number().min(0, "Quantity must be non-negative"),
379
+ UnitOfMeasurement: z3.nativeEnum(PricingMeasure),
380
+ UnitPrice: z3.number().min(0, "Unit price must be non-negative"),
381
+ UnitCurency: z3.nativeEnum(Currency),
382
+ Subtotal: z3.number().min(0, "Subtotal must be non-negative"),
383
+ Note: z3.string().nullable()
342
384
  });
343
- var createAppointmentSchema = z2.object({
344
- clinicBranchId: z2.string().min(MIN_STRING_LENGTH, "Clinic branch ID is required"),
345
- practitionerId: z2.string().min(MIN_STRING_LENGTH, "Practitioner ID is required"),
346
- patientId: z2.string().min(MIN_STRING_LENGTH, "Patient ID is required"),
347
- procedureId: z2.string().min(MIN_STRING_LENGTH, "Procedure ID is required"),
348
- appointmentStartTime: z2.any().refine(
385
+ var finalBillingSchema = z3.object({
386
+ subtotalAll: z3.number().min(0, "Subtotal all must be non-negative"),
387
+ taxRate: z3.number().min(0).max(1, "Tax rate must be between 0 and 1"),
388
+ taxPrice: z3.number().min(0, "Tax price must be non-negative"),
389
+ finalPrice: z3.number().min(0, "Final price must be non-negative"),
390
+ finalQuantity: z3.number().min(0, "Final quantity must be non-negative"),
391
+ currency: z3.nativeEnum(Currency),
392
+ unitOfMeasurement: z3.nativeEnum(PricingMeasure)
393
+ });
394
+ var appointmentMetadataSchema = z3.object({
395
+ selectedZones: z3.array(z3.string()).nullable(),
396
+ zonePhotos: z3.record(z3.string(), beforeAfterPerZoneSchema).nullable(),
397
+ zoneBilling: z3.record(z3.string(), billingPerZoneSchema).nullable(),
398
+ finalbilling: finalBillingSchema.nullable()
399
+ });
400
+ var createAppointmentSchema = z3.object({
401
+ clinicBranchId: z3.string().min(MIN_STRING_LENGTH, "Clinic branch ID is required"),
402
+ practitionerId: z3.string().min(MIN_STRING_LENGTH, "Practitioner ID is required"),
403
+ patientId: z3.string().min(MIN_STRING_LENGTH, "Patient ID is required"),
404
+ procedureId: z3.string().min(MIN_STRING_LENGTH, "Procedure ID is required"),
405
+ appointmentStartTime: z3.any().refine(
349
406
  (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
350
407
  "Appointment start time must be a valid timestamp or Date object"
351
408
  ),
352
- appointmentEndTime: z2.any().refine(
409
+ appointmentEndTime: z3.any().refine(
353
410
  (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
354
411
  "Appointment end time must be a valid timestamp or Date object"
355
412
  ),
356
- cost: z2.number().min(0, "Cost must be a non-negative number"),
357
- currency: z2.string().min(1, "Currency is required"),
358
- patientNotes: z2.string().max(MAX_STRING_LENGTH, "Patient notes too long").nullable().optional(),
413
+ cost: z3.number().min(0, "Cost must be a non-negative number"),
414
+ currency: z3.string().min(1, "Currency is required"),
415
+ patientNotes: z3.string().max(MAX_STRING_LENGTH, "Patient notes too long").nullable().optional(),
359
416
  initialStatus: appointmentStatusSchema,
360
417
  initialPaymentStatus: paymentStatusSchema.optional().default("unpaid" /* UNPAID */)
361
418
  }).refine((data) => data.appointmentEndTime > data.appointmentStartTime, {
362
419
  message: "Appointment end time must be after start time",
363
420
  path: ["appointmentEndTime"]
364
421
  });
365
- var updateAppointmentSchema = z2.object({
422
+ var updateAppointmentSchema = z3.object({
366
423
  status: appointmentStatusSchema.optional(),
367
- confirmationTime: z2.any().optional().nullable(),
368
- cancellationTime: z2.any().optional().nullable(),
369
- rescheduleTime: z2.any().optional().nullable(),
370
- procedureActualStartTime: z2.any().optional().nullable(),
371
- actualDurationMinutes: z2.number().int().positive("Duration must be a positive integer").optional(),
372
- cancellationReason: z2.string().max(MAX_STRING_LENGTH, "Cancellation reason too long").nullable().optional(),
373
- canceledBy: z2.enum(["patient", "clinic", "practitioner", "system"]).optional(),
374
- internalNotes: z2.string().max(MAX_STRING_LENGTH_LONG, "Internal notes too long").nullable().optional(),
375
- patientNotes: z2.any().optional().nullable(),
424
+ confirmationTime: z3.any().optional().nullable(),
425
+ cancellationTime: z3.any().optional().nullable(),
426
+ rescheduleTime: z3.any().optional().nullable(),
427
+ procedureActualStartTime: z3.any().optional().nullable(),
428
+ actualDurationMinutes: z3.number().int().positive("Duration must be a positive integer").optional(),
429
+ cancellationReason: z3.string().max(MAX_STRING_LENGTH, "Cancellation reason too long").nullable().optional(),
430
+ canceledBy: z3.enum(["patient", "clinic", "practitioner", "system"]).optional(),
431
+ internalNotes: z3.string().max(MAX_STRING_LENGTH_LONG, "Internal notes too long").nullable().optional(),
432
+ patientNotes: z3.any().optional().nullable(),
376
433
  paymentStatus: paymentStatusSchema.optional(),
377
- paymentTransactionId: z2.any().optional().nullable(),
378
- completedPreRequirements: z2.union([z2.array(z2.string()), z2.any()]).optional(),
379
- completedPostRequirements: z2.union([z2.array(z2.string()), z2.any()]).optional(),
380
- linkedFormIds: z2.union([z2.array(z2.string()), z2.any()]).optional(),
381
- pendingUserFormsIds: z2.union([z2.array(z2.string()), z2.any()]).optional(),
382
- appointmentStartTime: z2.any().refine(
434
+ paymentTransactionId: z3.any().optional().nullable(),
435
+ completedPreRequirements: z3.union([z3.array(z3.string()), z3.any()]).optional(),
436
+ completedPostRequirements: z3.union([z3.array(z3.string()), z3.any()]).optional(),
437
+ linkedFormIds: z3.union([z3.array(z3.string()), z3.any()]).optional(),
438
+ pendingUserFormsIds: z3.union([z3.array(z3.string()), z3.any()]).optional(),
439
+ appointmentStartTime: z3.any().refine(
383
440
  (val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
384
441
  "Appointment start time must be a valid timestamp or Date object"
385
442
  ).optional(),
386
- appointmentEndTime: z2.any().refine(
443
+ appointmentEndTime: z3.any().refine(
387
444
  (val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
388
445
  "Appointment end time must be a valid timestamp or Date object"
389
446
  ).optional(),
390
- calendarEventId: z2.string().min(MIN_STRING_LENGTH).optional(),
391
- cost: z2.number().min(0).optional(),
392
- clinicBranchId: z2.string().min(MIN_STRING_LENGTH).optional(),
393
- practitionerId: z2.string().min(MIN_STRING_LENGTH).optional(),
394
- linkedForms: z2.union([z2.array(linkedFormInfoSchema).max(MAX_ARRAY_LENGTH), z2.any()]).optional(),
395
- media: z2.union([
396
- z2.array(appointmentMediaItemSchema).max(MAX_ARRAY_LENGTH),
397
- z2.any()
447
+ calendarEventId: z3.string().min(MIN_STRING_LENGTH).optional(),
448
+ cost: z3.number().min(0).optional(),
449
+ clinicBranchId: z3.string().min(MIN_STRING_LENGTH).optional(),
450
+ practitionerId: z3.string().min(MIN_STRING_LENGTH).optional(),
451
+ linkedForms: z3.union([z3.array(linkedFormInfoSchema).max(MAX_ARRAY_LENGTH), z3.any()]).optional(),
452
+ media: z3.union([
453
+ z3.array(appointmentMediaItemSchema).max(MAX_ARRAY_LENGTH),
454
+ z3.any()
398
455
  ]).optional(),
399
- reviewInfo: z2.union([patientReviewInfoSchema.nullable(), z2.any()]).optional(),
400
- finalizedDetails: z2.union([finalizedDetailsSchema.nullable(), z2.any()]).optional(),
401
- isArchived: z2.boolean().optional(),
402
- updatedAt: z2.any().optional(),
403
- metadata: z2.any().optional()
456
+ reviewInfo: z3.union([patientReviewInfoSchema.nullable(), z3.any()]).optional(),
457
+ finalizedDetails: z3.union([finalizedDetailsSchema.nullable(), z3.any()]).optional(),
458
+ isArchived: z3.boolean().optional(),
459
+ updatedAt: z3.any().optional(),
460
+ metadata: appointmentMetadataSchema.optional()
404
461
  }).refine(
405
462
  (data) => {
406
463
  if (data.status === "canceled_clinic" /* CANCELED_CLINIC */ || data.status === "canceled_patient" /* CANCELED_PATIENT */ || data.status === "canceled_patient_rescheduled" /* CANCELED_PATIENT_RESCHEDULED */) {
@@ -424,24 +481,24 @@ var updateAppointmentSchema = z2.object({
424
481
  path: ["appointmentEndTime"]
425
482
  }
426
483
  );
427
- var searchAppointmentsSchema = z2.object({
428
- patientId: z2.string().optional(),
429
- practitionerId: z2.string().optional(),
430
- clinicBranchId: z2.string().optional(),
431
- startDate: z2.any().refine(
484
+ var searchAppointmentsSchema = z3.object({
485
+ patientId: z3.string().optional(),
486
+ practitionerId: z3.string().optional(),
487
+ clinicBranchId: z3.string().optional(),
488
+ startDate: z3.any().refine(
432
489
  (val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
433
490
  "Start date must be a valid timestamp or Date object"
434
491
  ).optional(),
435
- endDate: z2.any().refine(
492
+ endDate: z3.any().refine(
436
493
  (val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
437
494
  "End date must be a valid timestamp or Date object"
438
495
  ).optional(),
439
- status: z2.union([
496
+ status: z3.union([
440
497
  appointmentStatusSchema,
441
- z2.array(appointmentStatusSchema).nonempty()
498
+ z3.array(appointmentStatusSchema).nonempty()
442
499
  ]).optional(),
443
- limit: z2.number().positive().int().optional().default(20),
444
- startAfter: z2.any().optional()
500
+ limit: z3.number().positive().int().optional().default(20),
501
+ startAfter: z3.any().optional()
445
502
  }).refine(
446
503
  (data) => {
447
504
  if (!data.startDate && !data.endDate && !data.status) {
@@ -465,13 +522,13 @@ var searchAppointmentsSchema = z2.object({
465
522
  path: ["endDate"]
466
523
  }
467
524
  );
468
- var rescheduleAppointmentSchema = z2.object({
469
- appointmentId: z2.string().min(MIN_STRING_LENGTH, "Appointment ID is required"),
470
- newStartTime: z2.any().refine(
525
+ var rescheduleAppointmentSchema = z3.object({
526
+ appointmentId: z3.string().min(MIN_STRING_LENGTH, "Appointment ID is required"),
527
+ newStartTime: z3.any().refine(
471
528
  (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
472
529
  "New start time must be a valid timestamp, Date object, number, or string"
473
530
  ),
474
- newEndTime: z2.any().refine(
531
+ newEndTime: z3.any().refine(
475
532
  (val) => val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || (val == null ? void 0 : val.seconds) !== void 0 || typeof val === "number" || typeof val === "string" || val && typeof val.toMillis === "function",
476
533
  "New end time must be a valid timestamp, Date object, number, or string"
477
534
  )
@@ -591,24 +648,24 @@ var USERS_COLLECTION = "users";
591
648
  import { z as z20 } from "zod";
592
649
 
593
650
  // src/validations/schemas.ts
594
- import { z as z3 } from "zod";
595
- var emailSchema = z3.string().email("Invalid email format").min(5, "Email must be at least 5 characters").max(255, "Email must be less than 255 characters");
596
- var passwordSchema = z3.string().min(8, "Password must be at least 8 characters").max(100, "Password must be less than 100 characters").regex(
651
+ import { z as z4 } from "zod";
652
+ var emailSchema = z4.string().email("Invalid email format").min(5, "Email must be at least 5 characters").max(255, "Email must be less than 255 characters");
653
+ var passwordSchema = z4.string().min(8, "Password must be at least 8 characters").max(100, "Password must be less than 100 characters").regex(
597
654
  /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d\w\W]{8,}$/,
598
655
  "Password must contain at least one uppercase letter, one lowercase letter, and one number"
599
656
  );
600
- var userRoleSchema = z3.nativeEnum(UserRole);
601
- var userRolesSchema = z3.array(userRoleSchema).min(1, "User must have at least one role").max(3, "User cannot have more than 3 roles");
602
- var timestampSchema = z3.custom((data) => {
657
+ var userRoleSchema = z4.nativeEnum(UserRole);
658
+ var userRolesSchema = z4.array(userRoleSchema).min(1, "User must have at least one role").max(3, "User cannot have more than 3 roles");
659
+ var timestampSchema = z4.custom((data) => {
603
660
  if (data && typeof data === "object" && "isEqual" in data) {
604
661
  return true;
605
662
  }
606
663
  return data && typeof data === "object" && "toDate" in data && "seconds" in data && "nanoseconds" in data;
607
664
  }, "Must be a Timestamp object or serverTimestamp");
608
- var clinicAdminOptionsSchema = z3.object({
609
- isGroupOwner: z3.boolean(),
610
- groupToken: z3.string().optional(),
611
- groupId: z3.string().optional()
665
+ var clinicAdminOptionsSchema = z4.object({
666
+ isGroupOwner: z4.boolean(),
667
+ groupToken: z4.string().optional(),
668
+ groupId: z4.string().optional()
612
669
  }).refine(
613
670
  (data) => {
614
671
  if (!data.isGroupOwner && (!data.groupToken || !data.groupId)) {
@@ -623,20 +680,20 @@ var clinicAdminOptionsSchema = z3.object({
623
680
  message: "Invalid clinic admin options configuration"
624
681
  }
625
682
  );
626
- var createUserOptionsSchema = z3.object({
683
+ var createUserOptionsSchema = z4.object({
627
684
  clinicAdminData: clinicAdminOptionsSchema.optional()
628
685
  });
629
- var userSchema = z3.object({
630
- uid: z3.string(),
631
- email: z3.string().email().nullable(),
632
- roles: z3.array(userRoleSchema),
633
- isAnonymous: z3.boolean(),
686
+ var userSchema = z4.object({
687
+ uid: z4.string(),
688
+ email: z4.string().email().nullable(),
689
+ roles: z4.array(userRoleSchema),
690
+ isAnonymous: z4.boolean(),
634
691
  createdAt: timestampSchema,
635
692
  updatedAt: timestampSchema,
636
693
  lastLoginAt: timestampSchema,
637
- patientProfile: z3.string().optional(),
638
- practitionerProfile: z3.string().optional(),
639
- adminProfile: z3.string().optional()
694
+ patientProfile: z4.string().optional(),
695
+ practitionerProfile: z4.string().optional(),
696
+ adminProfile: z4.string().optional()
640
697
  });
641
698
 
642
699
  // src/errors/auth.errors.ts
@@ -1372,14 +1429,6 @@ var Gender = /* @__PURE__ */ ((Gender2) => {
1372
1429
  import { z as z7 } from "zod";
1373
1430
  import { Timestamp as Timestamp3 } from "firebase/firestore";
1374
1431
 
1375
- // src/validations/media.schema.ts
1376
- import { z as z4 } from "zod";
1377
- var mediaResourceSchema = z4.union([
1378
- z4.string().url(),
1379
- z4.instanceof(File),
1380
- z4.instanceof(Blob)
1381
- ]);
1382
-
1383
1432
  // src/validations/patient/medical-info.schema.ts
1384
1433
  import { z as z6 } from "zod";
1385
1434
 
@@ -3634,25 +3683,6 @@ var ProcedureFamily = /* @__PURE__ */ ((ProcedureFamily2) => {
3634
3683
  return ProcedureFamily2;
3635
3684
  })(ProcedureFamily || {});
3636
3685
 
3637
- // src/backoffice/types/static/pricing.types.ts
3638
- var PricingMeasure = /* @__PURE__ */ ((PricingMeasure3) => {
3639
- PricingMeasure3["PER_ML"] = "per_ml";
3640
- PricingMeasure3["PER_ZONE"] = "per_zone";
3641
- PricingMeasure3["PER_AREA"] = "per_area";
3642
- PricingMeasure3["PER_SESSION"] = "per_session";
3643
- PricingMeasure3["PER_TREATMENT"] = "per_treatment";
3644
- PricingMeasure3["PER_PACKAGE"] = "per_package";
3645
- return PricingMeasure3;
3646
- })(PricingMeasure || {});
3647
- var Currency = /* @__PURE__ */ ((Currency2) => {
3648
- Currency2["EUR"] = "EUR";
3649
- Currency2["USD"] = "USD";
3650
- Currency2["GBP"] = "GBP";
3651
- Currency2["CHF"] = "CHF";
3652
- Currency2["AUD"] = "AUD";
3653
- return Currency2;
3654
- })(Currency || {});
3655
-
3656
3686
  // src/validations/shared.schema.ts
3657
3687
  var sharedClinicContactInfoSchema = z12.object({
3658
3688
  email: z12.string().email(),
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@blackcode_sa/metaestetics-api",
3
3
  "private": false,
4
- "version": "1.7.38",
4
+ "version": "1.7.40",
5
5
  "description": "Firebase authentication service with anonymous upgrade support",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.mjs",
package/src/index.ts CHANGED
@@ -134,6 +134,10 @@ export type {
134
134
  CreateAppointmentHttpData,
135
135
  UpdateAppointmentData,
136
136
  SearchAppointmentsParams,
137
+ AppointmentMetadata,
138
+ BeforeAfterPerZone,
139
+ BillingPerZone,
140
+ FinalBilling,
137
141
  } from "./types/appointment";
138
142
  export {
139
143
  AppointmentStatus,
@@ -5,12 +5,16 @@ import {
5
5
  PatientProfileInfo,
6
6
  } from "../profile";
7
7
  import { ProcedureSummaryInfo } from "../procedure";
8
- import { Currency } from "../../backoffice/types/static/pricing.types";
8
+ import {
9
+ Currency,
10
+ type PricingMeasure,
11
+ } from "../../backoffice/types/static/pricing.types";
9
12
  import { BlockingCondition } from "../../backoffice/types/static/blocking-condition.types";
10
13
  import { Contraindication } from "../../backoffice/types/static/contraindication.types";
11
14
  import { Requirement } from "../../backoffice/types/requirement.types";
12
15
  import { FilledDocumentStatus } from "../documentation-templates";
13
16
  import type { ProcedureFamily } from "../../backoffice";
17
+ import type { MediaResource } from "../../services/media/media.service";
14
18
 
15
19
  /**
16
20
  * Enum defining the possible statuses of an appointment.
@@ -111,6 +115,74 @@ export interface PatientReviewInfo {
111
115
  reviewedAt: Timestamp;
112
116
  }
113
117
 
118
+ /**
119
+ * Interface for before/after photos and notes per zone
120
+ */
121
+ export interface BeforeAfterPerZone {
122
+ /** URL for before photo or null if not available */
123
+ before: MediaResource | null;
124
+ /** URL for after photo or null if not available */
125
+ after: MediaResource | null;
126
+ /** Optional note for the zone */
127
+ note: string | null;
128
+ }
129
+
130
+ /**
131
+ * Interface for billing information per zone
132
+ */
133
+ export interface BillingPerZone {
134
+ /** Product name/description */
135
+ Product: string;
136
+ /** Product ID */
137
+ ProductId: string | null;
138
+ /** Quantity used (can be decimal) */
139
+ Quantity: number;
140
+ /** Unit of measurement */
141
+ UnitOfMeasurement: PricingMeasure;
142
+ /** Unit price for the product */
143
+ UnitPrice: number;
144
+ /** Currency for the unit price */
145
+ UnitCurency: Currency;
146
+ /** Calculated subtotal */
147
+ Subtotal: number;
148
+ /** Optional billing note */
149
+ Note: string | null;
150
+ }
151
+
152
+ /**
153
+ * Interface for final billing calculations of the appointment
154
+ */
155
+ export interface FinalBilling {
156
+ /** Total of all subtotals from all zones */
157
+ subtotalAll: number;
158
+ /** Tax rate as percentage (e.g., 0.20 for 20%) */
159
+ taxRate: number;
160
+ /** Calculated tax amount */
161
+ taxPrice: number;
162
+ /** Final price including tax */
163
+ finalPrice: number;
164
+ /** Total final quantity across all zones */
165
+ finalQuantity: number;
166
+ /** Currency for the final billing */
167
+ currency: Currency;
168
+ /** Unit of measurement for the final billing */
169
+ unitOfMeasurement: PricingMeasure;
170
+ }
171
+
172
+ /**
173
+ * Interface for appointment metadata containing zone-specific information
174
+ */
175
+ export interface AppointmentMetadata {
176
+ /** Array of selected zones for the appointment */
177
+ selectedZones: string[] | null;
178
+ /** Map of zone photos with before/after images and notes */
179
+ zonePhotos: Record<string, BeforeAfterPerZone> | null;
180
+ /** Map of billing information per zone */
181
+ zoneBilling: Record<string, BillingPerZone> | null;
182
+ /** Final billing calculations for the appointment */
183
+ finalbilling: FinalBilling | null;
184
+ }
185
+
114
186
  /**
115
187
  * Represents a booked appointment, aggregating key information and relevant procedure rules.
116
188
  */
@@ -209,7 +281,7 @@ export interface Appointment {
209
281
  isArchived?: boolean;
210
282
 
211
283
  /** NEW: Metadata for the appointment - used for area selection and photos */
212
- metadata?: any;
284
+ metadata?: AppointmentMetadata;
213
285
  }
214
286
 
215
287
  /**
@@ -284,7 +356,7 @@ export interface UpdateAppointmentData {
284
356
  updatedAt?: FieldValue; // To set server timestamp
285
357
 
286
358
  /** NEW: For updating metadata */
287
- metadata?: any;
359
+ metadata?: AppointmentMetadata;
288
360
  }
289
361
 
290
362
  /**
@@ -5,6 +5,11 @@ import {
5
5
  MediaType,
6
6
  } from "../types/appointment";
7
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";
8
13
 
9
14
  // Define common constants locally if not available from common.schema.ts
10
15
  const MIN_STRING_LENGTH = 1;
@@ -147,6 +152,52 @@ export const finalizedDetailsSchema = z.object({
147
152
  .optional(),
148
153
  });
149
154
 
155
+ /**
156
+ * Schema for before/after photos and notes per zone
157
+ */
158
+ export const beforeAfterPerZoneSchema = z.object({
159
+ before: mediaResourceSchema.nullable(),
160
+ after: mediaResourceSchema.nullable(),
161
+ note: z.string().nullable(),
162
+ });
163
+
164
+ /**
165
+ * Schema for billing information per zone
166
+ */
167
+ export const billingPerZoneSchema = z.object({
168
+ Product: z.string().min(MIN_STRING_LENGTH, "Product name is required"),
169
+ ProductId: z.string().nullable(),
170
+ Quantity: z.number().min(0, "Quantity must be non-negative"),
171
+ UnitOfMeasurement: z.nativeEnum(PricingMeasure),
172
+ UnitPrice: z.number().min(0, "Unit price must be non-negative"),
173
+ UnitCurency: z.nativeEnum(Currency),
174
+ Subtotal: z.number().min(0, "Subtotal must be non-negative"),
175
+ Note: z.string().nullable(),
176
+ });
177
+
178
+ /**
179
+ * Schema for final billing calculations of the appointment
180
+ */
181
+ 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"),
187
+ currency: z.nativeEnum(Currency),
188
+ unitOfMeasurement: z.nativeEnum(PricingMeasure),
189
+ });
190
+
191
+ /**
192
+ * Schema for appointment metadata containing zone-specific information
193
+ */
194
+ export const appointmentMetadataSchema = z.object({
195
+ selectedZones: z.array(z.string()).nullable(),
196
+ zonePhotos: z.record(z.string(), beforeAfterPerZoneSchema).nullable(),
197
+ zoneBilling: z.record(z.string(), billingPerZoneSchema).nullable(),
198
+ finalbilling: finalBillingSchema.nullable(),
199
+ });
200
+
150
201
  // --- Main Appointment Schemas ---
151
202
 
152
203
  /**
@@ -291,7 +342,7 @@ export const updateAppointmentSchema = z
291
342
  .optional(),
292
343
  isArchived: z.boolean().optional(),
293
344
  updatedAt: z.any().optional(),
294
- metadata: z.any().optional(),
345
+ metadata: appointmentMetadataSchema.optional(),
295
346
  })
296
347
  .refine(
297
348
  (data) => {