@blackcode_sa/metaestetics-api 1.6.4 → 1.6.5

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.js CHANGED
@@ -573,7 +573,6 @@ var finalizedDetailsSchema = import_zod2.z.object({
573
573
  notes: import_zod2.z.string().max(MAX_STRING_LENGTH_LONG, "Finalization notes too long").optional()
574
574
  });
575
575
  var createAppointmentSchema = import_zod2.z.object({
576
- calendarEventId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Calendar event ID is required"),
577
576
  clinicBranchId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Clinic branch ID is required"),
578
577
  practitionerId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Practitioner ID is required"),
579
578
  patientId: import_zod2.z.string().min(MIN_STRING_LENGTH, "Patient ID is required"),
@@ -610,6 +609,7 @@ var updateAppointmentSchema = import_zod2.z.object({
610
609
  paymentTransactionId: import_zod2.z.any().optional().nullable(),
611
610
  completedPreRequirements: import_zod2.z.union([import_zod2.z.array(import_zod2.z.string()), import_zod2.z.any()]).optional(),
612
611
  completedPostRequirements: import_zod2.z.union([import_zod2.z.array(import_zod2.z.string()), import_zod2.z.any()]).optional(),
612
+ linkedFormIds: import_zod2.z.union([import_zod2.z.array(import_zod2.z.string()), import_zod2.z.any()]).optional(),
613
613
  pendingUserFormsIds: import_zod2.z.union([import_zod2.z.array(import_zod2.z.string()), import_zod2.z.any()]).optional(),
614
614
  appointmentStartTime: import_zod2.z.any().refine(
615
615
  (val) => val === void 0 || val instanceof Date || (val == null ? void 0 : val._seconds) !== void 0 || typeof val === "number",
@@ -7712,7 +7712,8 @@ var createProcedureSchema = import_zod20.z.object({
7712
7712
  duration: import_zod20.z.number().min(1).max(480),
7713
7713
  // Max 8 hours
7714
7714
  practitionerId: import_zod20.z.string().min(1),
7715
- clinicBranchId: import_zod20.z.string().min(1)
7715
+ clinicBranchId: import_zod20.z.string().min(1),
7716
+ photos: import_zod20.z.array(import_zod20.z.string()).optional()
7716
7717
  });
7717
7718
  var updateProcedureSchema = import_zod20.z.object({
7718
7719
  name: import_zod20.z.string().min(3).max(100).optional(),
@@ -7727,7 +7728,8 @@ var updateProcedureSchema = import_zod20.z.object({
7727
7728
  subcategoryId: import_zod20.z.string().optional(),
7728
7729
  technologyId: import_zod20.z.string().optional(),
7729
7730
  productId: import_zod20.z.string().optional(),
7730
- clinicBranchId: import_zod20.z.string().optional()
7731
+ clinicBranchId: import_zod20.z.string().optional(),
7732
+ photos: import_zod20.z.array(import_zod20.z.string()).optional()
7731
7733
  });
7732
7734
  var procedureSchema = createProcedureSchema.extend({
7733
7735
  id: import_zod20.z.string().min(1),
@@ -7741,6 +7743,8 @@ var procedureSchema = createProcedureSchema.extend({
7741
7743
  // We'll validate the full product object separately
7742
7744
  blockingConditions: import_zod20.z.array(import_zod20.z.any()),
7743
7745
  // We'll validate blocking conditions separately
7746
+ contraindications: import_zod20.z.array(import_zod20.z.any()),
7747
+ // We'll validate contraindications separately
7744
7748
  treatmentBenefits: import_zod20.z.array(import_zod20.z.any()),
7745
7749
  // We'll validate treatment benefits separately
7746
7750
  preRequirements: import_zod20.z.array(import_zod20.z.any()),
@@ -7845,6 +7849,7 @@ var ProcedureService = class extends BaseService {
7845
7849
  technology,
7846
7850
  product,
7847
7851
  blockingConditions: technology.blockingConditions,
7852
+ contraindications: technology.contraindications || [],
7848
7853
  treatmentBenefits: technology.benefits,
7849
7854
  preRequirements: technology.requirements.pre,
7850
7855
  postRequirements: technology.requirements.post,
@@ -12163,166 +12168,6 @@ var import_firestore39 = require("firebase/firestore");
12163
12168
  var TECHNOLOGIES_COLLECTION = "technologies";
12164
12169
 
12165
12170
  // src/services/appointment/utils/appointment.utils.ts
12166
- async function fetchAggregatedInfoUtil(db, clinicId, practitionerId, patientId, procedureId) {
12167
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
12168
- try {
12169
- const [clinicDoc, practitionerDoc, patientDoc, procedureDoc] = await Promise.all([
12170
- (0, import_firestore39.getDoc)((0, import_firestore39.doc)(db, CLINICS_COLLECTION, clinicId)),
12171
- (0, import_firestore39.getDoc)((0, import_firestore39.doc)(db, PRACTITIONERS_COLLECTION, practitionerId)),
12172
- (0, import_firestore39.getDoc)((0, import_firestore39.doc)(db, PATIENTS_COLLECTION, patientId)),
12173
- (0, import_firestore39.getDoc)((0, import_firestore39.doc)(db, PROCEDURES_COLLECTION, procedureId))
12174
- ]);
12175
- if (!clinicDoc.exists()) {
12176
- throw new Error(`Clinic with ID ${clinicId} not found`);
12177
- }
12178
- if (!practitionerDoc.exists()) {
12179
- throw new Error(`Practitioner with ID ${practitionerId} not found`);
12180
- }
12181
- if (!patientDoc.exists()) {
12182
- throw new Error(`Patient with ID ${patientId} not found`);
12183
- }
12184
- if (!procedureDoc.exists()) {
12185
- throw new Error(`Procedure with ID ${procedureId} not found`);
12186
- }
12187
- const clinicData = clinicDoc.data();
12188
- const practitionerData = practitionerDoc.data();
12189
- const patientData = patientDoc.data();
12190
- const procedureData = procedureDoc.data();
12191
- const clinicInfo = {
12192
- id: clinicId,
12193
- featuredPhoto: ((_a = clinicData.featuredPhotos) == null ? void 0 : _a[0]) || "",
12194
- name: clinicData.name,
12195
- description: clinicData.description || null,
12196
- location: clinicData.location,
12197
- contactInfo: clinicData.contactInfo
12198
- };
12199
- const practitionerInfo = {
12200
- id: practitionerId,
12201
- practitionerPhoto: ((_b = practitionerData.basicInfo) == null ? void 0 : _b.profileImageUrl) || null,
12202
- name: `${((_c = practitionerData.basicInfo) == null ? void 0 : _c.firstName) || ""} ${((_d = practitionerData.basicInfo) == null ? void 0 : _d.lastName) || ""}`.trim(),
12203
- email: ((_e = practitionerData.basicInfo) == null ? void 0 : _e.email) || "",
12204
- phone: ((_f = practitionerData.basicInfo) == null ? void 0 : _f.phoneNumber) || null,
12205
- certification: practitionerData.certification
12206
- };
12207
- const patientInfo = {
12208
- id: patientId,
12209
- fullName: patientData.displayName || "",
12210
- email: patientData.email || "",
12211
- phone: patientData.phoneNumber || null,
12212
- dateOfBirth: patientData.dateOfBirth || import_firestore39.Timestamp.now(),
12213
- gender: patientData.gender || "other"
12214
- };
12215
- const procedureInfo = {
12216
- id: procedureId,
12217
- name: procedureData.name,
12218
- description: procedureData.description,
12219
- photo: procedureData.photo || "",
12220
- family: procedureData.family,
12221
- categoryName: ((_g = procedureData.category) == null ? void 0 : _g.name) || "",
12222
- subcategoryName: ((_h = procedureData.subcategory) == null ? void 0 : _h.name) || "",
12223
- technologyName: ((_i = procedureData.technology) == null ? void 0 : _i.name) || "",
12224
- brandName: ((_j = procedureData.product) == null ? void 0 : _j.brand) || "",
12225
- productName: ((_k = procedureData.product) == null ? void 0 : _k.name) || "",
12226
- price: procedureData.price || 0,
12227
- pricingMeasure: procedureData.pricingMeasure,
12228
- currency: procedureData.currency,
12229
- duration: procedureData.duration || 0,
12230
- clinicId,
12231
- clinicName: clinicInfo.name,
12232
- practitionerId,
12233
- practitionerName: practitionerInfo.name
12234
- };
12235
- let technologyId = "";
12236
- if ((_l = procedureData.technology) == null ? void 0 : _l.id) {
12237
- technologyId = procedureData.technology.id;
12238
- }
12239
- let blockingConditions = [];
12240
- let contraindications = [];
12241
- let preProcedureRequirements = [];
12242
- let postProcedureRequirements = [];
12243
- if (technologyId) {
12244
- const technologyDoc = await (0, import_firestore39.getDoc)(
12245
- (0, import_firestore39.doc)(db, TECHNOLOGIES_COLLECTION, technologyId)
12246
- );
12247
- if (technologyDoc.exists()) {
12248
- const technologyData = technologyDoc.data();
12249
- blockingConditions = technologyData.blockingConditions || [];
12250
- contraindications = technologyData.contraindications || [];
12251
- preProcedureRequirements = ((_m = technologyData.requirements) == null ? void 0 : _m.pre) || [];
12252
- postProcedureRequirements = ((_n = technologyData.requirements) == null ? void 0 : _n.post) || [];
12253
- }
12254
- } else {
12255
- blockingConditions = procedureData.blockingConditions || [];
12256
- contraindications = procedureData.contraindications || [];
12257
- preProcedureRequirements = procedureData.preRequirements || [];
12258
- postProcedureRequirements = procedureData.postRequirements || [];
12259
- }
12260
- return {
12261
- clinicInfo,
12262
- practitionerInfo,
12263
- patientInfo,
12264
- procedureInfo,
12265
- blockingConditions,
12266
- contraindications,
12267
- preProcedureRequirements,
12268
- postProcedureRequirements
12269
- };
12270
- } catch (error) {
12271
- console.error("Error fetching aggregated info:", error);
12272
- throw error;
12273
- }
12274
- }
12275
- async function createAppointmentUtil2(db, data, aggregatedInfo, generateId2) {
12276
- try {
12277
- const appointmentId = generateId2();
12278
- const appointment = {
12279
- id: appointmentId,
12280
- calendarEventId: data.calendarEventId,
12281
- clinicBranchId: data.clinicBranchId,
12282
- clinicInfo: aggregatedInfo.clinicInfo,
12283
- practitionerId: data.practitionerId,
12284
- practitionerInfo: aggregatedInfo.practitionerInfo,
12285
- patientId: data.patientId,
12286
- patientInfo: aggregatedInfo.patientInfo,
12287
- procedureId: data.procedureId,
12288
- procedureInfo: aggregatedInfo.procedureInfo,
12289
- status: data.initialStatus,
12290
- bookingTime: import_firestore39.Timestamp.now(),
12291
- appointmentStartTime: data.appointmentStartTime,
12292
- appointmentEndTime: data.appointmentEndTime,
12293
- patientNotes: data.patientNotes || null,
12294
- cost: data.cost,
12295
- currency: data.currency,
12296
- paymentStatus: data.initialPaymentStatus || "unpaid" /* UNPAID */,
12297
- blockingConditions: aggregatedInfo.blockingConditions,
12298
- contraindications: aggregatedInfo.contraindications,
12299
- preProcedureRequirements: aggregatedInfo.preProcedureRequirements,
12300
- postProcedureRequirements: aggregatedInfo.postProcedureRequirements,
12301
- completedPreRequirements: [],
12302
- completedPostRequirements: [],
12303
- createdAt: (0, import_firestore39.serverTimestamp)(),
12304
- updatedAt: (0, import_firestore39.serverTimestamp)()
12305
- };
12306
- if (data.initialStatus === "confirmed" /* CONFIRMED */) {
12307
- appointment.confirmationTime = import_firestore39.Timestamp.now();
12308
- }
12309
- await (0, import_firestore39.setDoc)((0, import_firestore39.doc)(db, APPOINTMENTS_COLLECTION, appointmentId), appointment);
12310
- const calendarEventRef = (0, import_firestore39.doc)(db, CALENDAR_COLLECTION, data.calendarEventId);
12311
- await (0, import_firestore39.updateDoc)(calendarEventRef, {
12312
- appointmentId,
12313
- updatedAt: (0, import_firestore39.serverTimestamp)()
12314
- });
12315
- const now = import_firestore39.Timestamp.now();
12316
- return {
12317
- ...appointment,
12318
- createdAt: now,
12319
- updatedAt: now
12320
- };
12321
- } catch (error) {
12322
- console.error("Error creating appointment:", error);
12323
- throw error;
12324
- }
12325
- }
12326
12171
  async function updateAppointmentUtil2(db, appointmentId, data) {
12327
12172
  try {
12328
12173
  const appointmentRef = (0, import_firestore39.doc)(db, APPOINTMENTS_COLLECTION, appointmentId);
@@ -12530,78 +12375,6 @@ var AppointmentService = class extends BaseService {
12530
12375
  this.filledDocumentService = filledDocumentService;
12531
12376
  this.functions = (0, import_functions.getFunctions)(app, "europe-west6");
12532
12377
  }
12533
- /**
12534
- * Test method using the callable function version of getAvailableBookingSlots
12535
- * For development and testing purposes only - not for production use
12536
- *
12537
- * @param clinicId ID of the clinic
12538
- * @param practitionerId ID of the practitioner
12539
- * @param procedureId ID of the procedure
12540
- * @param startDate Start date of the time range to check
12541
- * @param endDate End date of the time range to check
12542
- * @returns Test result from the callable function
12543
- */
12544
- async testGetAvailableBookingSlots(clinicId, practitionerId, procedureId, startDate, endDate) {
12545
- try {
12546
- console.log(
12547
- `[APPOINTMENT_SERVICE] Testing callable function for clinic: ${clinicId}, practitioner: ${practitionerId}, procedure: ${procedureId}`
12548
- );
12549
- const getAvailableBookingSlotsCallable = (0, import_functions.httpsCallable)(
12550
- this.functions,
12551
- "getAvailableBookingSlots"
12552
- );
12553
- const result = await getAvailableBookingSlotsCallable({
12554
- clinicId,
12555
- practitionerId,
12556
- procedureId,
12557
- timeframe: {
12558
- start: startDate.getTime(),
12559
- end: endDate.getTime()
12560
- }
12561
- });
12562
- console.log(
12563
- "[APPOINTMENT_SERVICE] Callable function test result:",
12564
- result.data
12565
- );
12566
- return result.data;
12567
- } catch (error) {
12568
- console.error(
12569
- "[APPOINTMENT_SERVICE] Error testing callable function:",
12570
- error
12571
- );
12572
- throw error;
12573
- }
12574
- }
12575
- /**
12576
- * Gets available booking slots for a specific clinic, practitioner, and procedure.
12577
- *
12578
- * @param clinicId ID of the clinic
12579
- * @param practitionerId ID of the practitioner
12580
- * @param procedureId ID of the procedure
12581
- * @param startDate Start date of the time range to check
12582
- * @param endDate End date of the time range to check
12583
- * @returns Array of available booking slots
12584
- */
12585
- async getAvailableBookingSlots(clinicId, practitionerId, procedureId, startDate, endDate) {
12586
- try {
12587
- console.log(
12588
- `[APPOINTMENT_SERVICE] Getting available booking slots for clinic: ${clinicId}, practitioner: ${practitionerId}, procedure: ${procedureId}`
12589
- );
12590
- return this.getAvailableBookingSlotsHttp(
12591
- clinicId,
12592
- practitionerId,
12593
- procedureId,
12594
- startDate,
12595
- endDate
12596
- );
12597
- } catch (error) {
12598
- console.error(
12599
- "[APPOINTMENT_SERVICE] Error getting available booking slots:",
12600
- error
12601
- );
12602
- throw error;
12603
- }
12604
- }
12605
12378
  /**
12606
12379
  * Gets available booking slots for a specific clinic, practitioner, and procedure using HTTP request.
12607
12380
  * This is an alternative implementation using direct HTTP request instead of callable function.
@@ -12703,34 +12476,81 @@ var AppointmentService = class extends BaseService {
12703
12476
  }
12704
12477
  }
12705
12478
  /**
12706
- * Creates a new appointment.
12479
+ * Creates an appointment via the Cloud Function orchestrateAppointmentCreation
12707
12480
  *
12708
- * @param data Data needed to create the appointment
12481
+ * @param data - CreateAppointmentData object
12709
12482
  * @returns The created appointment
12710
12483
  */
12711
- async createAppointment(data) {
12484
+ async createAppointmentHttp(data) {
12712
12485
  try {
12713
- console.log("[APPOINTMENT_SERVICE] Creating appointment");
12714
- const validatedData = await createAppointmentSchema.parseAsync(data);
12715
- const aggregatedInfo = await fetchAggregatedInfoUtil(
12716
- this.db,
12717
- validatedData.clinicBranchId,
12718
- validatedData.practitionerId,
12719
- validatedData.patientId,
12720
- validatedData.procedureId
12486
+ console.log(
12487
+ "[APPOINTMENT_SERVICE] Creating appointment via cloud function"
12721
12488
  );
12722
- const appointment = await createAppointmentUtil2(
12723
- this.db,
12724
- validatedData,
12725
- aggregatedInfo,
12726
- this.generateId.bind(this)
12489
+ const currentUser = this.auth.currentUser;
12490
+ if (!currentUser) {
12491
+ throw new Error("User must be authenticated to create an appointment");
12492
+ }
12493
+ const idToken = await currentUser.getIdToken();
12494
+ const functionUrl = `https://europe-west6-metaestetics.cloudfunctions.net/bookingApi/orchestrateAppointmentCreation`;
12495
+ const requestData = {
12496
+ patientId: data.patientId,
12497
+ procedureId: data.procedureId,
12498
+ appointmentStartTime: data.appointmentStartTime.toMillis ? data.appointmentStartTime.toMillis() : new Date(data.appointmentStartTime).getTime(),
12499
+ appointmentEndTime: data.appointmentEndTime.toMillis ? data.appointmentEndTime.toMillis() : new Date(data.appointmentEndTime).getTime(),
12500
+ patientNotes: data.patientNotes || null
12501
+ };
12502
+ console.log(
12503
+ `[APPOINTMENT_SERVICE] Making fetch request to ${functionUrl}`
12727
12504
  );
12505
+ const response = await fetch(functionUrl, {
12506
+ method: "POST",
12507
+ mode: "cors",
12508
+ cache: "no-cache",
12509
+ credentials: "omit",
12510
+ headers: {
12511
+ "Content-Type": "application/json",
12512
+ Authorization: `Bearer ${idToken}`
12513
+ },
12514
+ redirect: "follow",
12515
+ referrerPolicy: "no-referrer",
12516
+ body: JSON.stringify(requestData)
12517
+ });
12728
12518
  console.log(
12729
- `[APPOINTMENT_SERVICE] Appointment created with ID: ${appointment.id}`
12519
+ `[APPOINTMENT_SERVICE] Received response ${response.status}: ${response.statusText}`
12730
12520
  );
12731
- return appointment;
12521
+ if (!response.ok) {
12522
+ const errorText = await response.text();
12523
+ console.error(
12524
+ `[APPOINTMENT_SERVICE] Error response details: ${errorText}`
12525
+ );
12526
+ throw new Error(
12527
+ `Failed to create appointment: ${response.status} ${response.statusText} - ${errorText}`
12528
+ );
12529
+ }
12530
+ const result = await response.json();
12531
+ if (!result.success) {
12532
+ throw new Error(result.error || "Failed to create appointment");
12533
+ }
12534
+ if (result.appointmentData) {
12535
+ console.log(
12536
+ `[APPOINTMENT_SERVICE] Appointment created with ID: ${result.appointmentId}`
12537
+ );
12538
+ return result.appointmentData;
12539
+ }
12540
+ const createdAppointment = await this.getAppointmentById(
12541
+ result.appointmentId
12542
+ );
12543
+ if (!createdAppointment) {
12544
+ throw new Error(
12545
+ `Failed to retrieve created appointment with ID: ${result.appointmentId}`
12546
+ );
12547
+ }
12548
+ return createdAppointment;
12732
12549
  } catch (error) {
12733
- console.error("[APPOINTMENT_SERVICE] Error creating appointment:", error);
12550
+ console.error(
12551
+ "[APPOINTMENT_SERVICE] Error creating appointment via cloud function:",
12552
+ error
12553
+ );
12734
12554
  throw error;
12735
12555
  }
12736
12556
  }
@@ -13220,38 +13040,6 @@ var AppointmentService = class extends BaseService {
13220
13040
  };
13221
13041
  return this.updateAppointment(appointmentId, updateData);
13222
13042
  }
13223
- /**
13224
- * Marks pre-procedure requirements as completed.
13225
- *
13226
- * @param appointmentId ID of the appointment
13227
- * @param requirementIds IDs of the requirements to mark as completed
13228
- * @returns The updated appointment
13229
- */
13230
- async completePreRequirements(appointmentId, requirementIds) {
13231
- console.log(
13232
- `[APPOINTMENT_SERVICE] Marking pre-requirements as completed for appointment: ${appointmentId}`
13233
- );
13234
- const updateData = {
13235
- completedPreRequirements: requirementIds
13236
- };
13237
- return this.updateAppointment(appointmentId, updateData);
13238
- }
13239
- /**
13240
- * Marks post-procedure requirements as completed.
13241
- *
13242
- * @param appointmentId ID of the appointment
13243
- * @param requirementIds IDs of the requirements to mark as completed
13244
- * @returns The updated appointment
13245
- */
13246
- async completePostRequirements(appointmentId, requirementIds) {
13247
- console.log(
13248
- `[APPOINTMENT_SERVICE] Marking post-requirements as completed for appointment: ${appointmentId}`
13249
- );
13250
- const updateData = {
13251
- completedPostRequirements: requirementIds
13252
- };
13253
- return this.updateAppointment(appointmentId, updateData);
13254
- }
13255
13043
  /**
13256
13044
  * Updates the internal notes of an appointment.
13257
13045
  *
@@ -13268,25 +13056,6 @@ var AppointmentService = class extends BaseService {
13268
13056
  };
13269
13057
  return this.updateAppointment(appointmentId, updateData);
13270
13058
  }
13271
- /**
13272
- * Debug helper: Get the current user's ID token for testing purposes
13273
- * Use this token in Postman with Authorization: Bearer TOKEN
13274
- */
13275
- async getDebugToken() {
13276
- try {
13277
- const currentUser = this.auth.currentUser;
13278
- if (!currentUser) {
13279
- console.log("[APPOINTMENT_SERVICE] No user is signed in");
13280
- return null;
13281
- }
13282
- const idToken = await currentUser.getIdToken();
13283
- console.log("[APPOINTMENT_SERVICE] Debug token:", idToken);
13284
- return idToken;
13285
- } catch (error) {
13286
- console.error("[APPOINTMENT_SERVICE] Error getting debug token:", error);
13287
- return null;
13288
- }
13289
- }
13290
13059
  };
13291
13060
 
13292
13061
  // src/services/patient/patientRequirements.service.ts