@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/admin/index.d.mts +67 -3
- package/dist/admin/index.d.ts +67 -3
- package/dist/index.d.mts +354 -14
- package/dist/index.d.ts +354 -14
- package/dist/index.js +180 -150
- package/dist/index.mjs +177 -147
- package/package.json +1 -1
- package/src/index.ts +4 -0
- package/src/types/appointment/index.ts +75 -3
- package/src/validations/appointment.schema.ts +52 -1
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/validations/appointment.schema.ts
|
|
2
|
-
import { z as
|
|
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 =
|
|
276
|
-
var paymentStatusSchema =
|
|
277
|
-
var mediaTypeSchema =
|
|
278
|
-
var appointmentMediaItemSchema =
|
|
279
|
-
id:
|
|
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:
|
|
282
|
-
fileName:
|
|
283
|
-
uploadedAt:
|
|
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:
|
|
288
|
-
description:
|
|
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 =
|
|
291
|
-
id:
|
|
292
|
-
name:
|
|
293
|
-
description:
|
|
294
|
-
cost:
|
|
295
|
-
duration:
|
|
296
|
-
procedureFamily:
|
|
297
|
-
procedureCategoryId:
|
|
298
|
-
procedureCategoryName:
|
|
299
|
-
procedureSubCategoryId:
|
|
300
|
-
procedureSubCategoryName:
|
|
301
|
-
procedureTechnologyId:
|
|
302
|
-
procedureTechnologyName:
|
|
303
|
-
procedureProductBrandId:
|
|
304
|
-
procedureProductBrandName:
|
|
305
|
-
procedureProductId:
|
|
306
|
-
procedureProductName:
|
|
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 =
|
|
309
|
-
formId:
|
|
310
|
-
templateId:
|
|
311
|
-
templateVersion:
|
|
312
|
-
title:
|
|
313
|
-
isUserForm:
|
|
314
|
-
isRequired:
|
|
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:
|
|
317
|
-
submittedAt:
|
|
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:
|
|
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 =
|
|
327
|
-
reviewId:
|
|
328
|
-
rating:
|
|
329
|
-
comment:
|
|
330
|
-
reviewedAt:
|
|
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 =
|
|
336
|
-
by:
|
|
337
|
-
at:
|
|
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:
|
|
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
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
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:
|
|
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:
|
|
357
|
-
currency:
|
|
358
|
-
patientNotes:
|
|
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 =
|
|
422
|
+
var updateAppointmentSchema = z3.object({
|
|
366
423
|
status: appointmentStatusSchema.optional(),
|
|
367
|
-
confirmationTime:
|
|
368
|
-
cancellationTime:
|
|
369
|
-
rescheduleTime:
|
|
370
|
-
procedureActualStartTime:
|
|
371
|
-
actualDurationMinutes:
|
|
372
|
-
cancellationReason:
|
|
373
|
-
canceledBy:
|
|
374
|
-
internalNotes:
|
|
375
|
-
patientNotes:
|
|
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:
|
|
378
|
-
completedPreRequirements:
|
|
379
|
-
completedPostRequirements:
|
|
380
|
-
linkedFormIds:
|
|
381
|
-
pendingUserFormsIds:
|
|
382
|
-
appointmentStartTime:
|
|
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:
|
|
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:
|
|
391
|
-
cost:
|
|
392
|
-
clinicBranchId:
|
|
393
|
-
practitionerId:
|
|
394
|
-
linkedForms:
|
|
395
|
-
media:
|
|
396
|
-
|
|
397
|
-
|
|
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:
|
|
400
|
-
finalizedDetails:
|
|
401
|
-
isArchived:
|
|
402
|
-
updatedAt:
|
|
403
|
-
metadata:
|
|
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 =
|
|
428
|
-
patientId:
|
|
429
|
-
practitionerId:
|
|
430
|
-
clinicBranchId:
|
|
431
|
-
startDate:
|
|
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:
|
|
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:
|
|
496
|
+
status: z3.union([
|
|
440
497
|
appointmentStatusSchema,
|
|
441
|
-
|
|
498
|
+
z3.array(appointmentStatusSchema).nonempty()
|
|
442
499
|
]).optional(),
|
|
443
|
-
limit:
|
|
444
|
-
startAfter:
|
|
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 =
|
|
469
|
-
appointmentId:
|
|
470
|
-
newStartTime:
|
|
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:
|
|
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
|
|
595
|
-
var emailSchema =
|
|
596
|
-
var passwordSchema =
|
|
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 =
|
|
601
|
-
var userRolesSchema =
|
|
602
|
-
var timestampSchema =
|
|
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 =
|
|
609
|
-
isGroupOwner:
|
|
610
|
-
groupToken:
|
|
611
|
-
groupId:
|
|
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 =
|
|
683
|
+
var createUserOptionsSchema = z4.object({
|
|
627
684
|
clinicAdminData: clinicAdminOptionsSchema.optional()
|
|
628
685
|
});
|
|
629
|
-
var userSchema =
|
|
630
|
-
uid:
|
|
631
|
-
email:
|
|
632
|
-
roles:
|
|
633
|
-
isAnonymous:
|
|
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:
|
|
638
|
-
practitionerProfile:
|
|
639
|
-
adminProfile:
|
|
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
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 {
|
|
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?:
|
|
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?:
|
|
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:
|
|
345
|
+
metadata: appointmentMetadataSchema.optional(),
|
|
295
346
|
})
|
|
296
347
|
.refine(
|
|
297
348
|
(data) => {
|