@blackcode_sa/metaestetics-api 1.14.43 → 1.14.45

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.
@@ -1677,9 +1677,20 @@ interface BeforeAfterPerZone {
1677
1677
  before: MediaResource | null;
1678
1678
  /** URL for after photo or null if not available */
1679
1679
  after: MediaResource | null;
1680
- /** Optional note for the zone */
1681
- afterNote?: string | null;
1680
+ /** Optional note for the before photo */
1682
1681
  beforeNote?: string | null;
1682
+ /** Optional note for the after photo */
1683
+ afterNote?: string | null;
1684
+ /** Whether this photo pair (before AND after) should be visible to the patient */
1685
+ showToPatient?: boolean;
1686
+ /** Whether the before note should be visible to the patient */
1687
+ beforeNoteVisibleToPatient?: boolean;
1688
+ /** Whether the after note should be visible to the patient */
1689
+ afterNoteVisibleToPatient?: boolean;
1690
+ /** Timestamp when visibility was last updated */
1691
+ visibilityUpdatedAt?: Timestamp;
1692
+ /** ID of the doctor who last updated visibility */
1693
+ visibilityUpdatedBy?: string;
1683
1694
  }
1684
1695
  /**
1685
1696
  * Interface for zone item data (products or notes per zone)
@@ -1786,7 +1797,14 @@ interface AppointmentMetadata {
1786
1797
  extendedProcedures?: ExtendedProcedureInfo[];
1787
1798
  recommendedProcedures: RecommendedProcedure[];
1788
1799
  finalbilling: FinalBilling | null;
1789
- finalizationNotes: string | null;
1800
+ /** Final treatment notes shared with patient */
1801
+ finalizationNotesShared?: string | null;
1802
+ /** Final treatment notes for internal use only (not shared with patient) */
1803
+ finalizationNotesInternal?: string | null;
1804
+ /**
1805
+ * @deprecated Use finalizationNotesShared instead. Kept for backward compatibility during migration.
1806
+ */
1807
+ finalizationNotes?: string | null;
1790
1808
  /**
1791
1809
  * @deprecated Use zonesData instead
1792
1810
  */
@@ -1677,9 +1677,20 @@ interface BeforeAfterPerZone {
1677
1677
  before: MediaResource | null;
1678
1678
  /** URL for after photo or null if not available */
1679
1679
  after: MediaResource | null;
1680
- /** Optional note for the zone */
1681
- afterNote?: string | null;
1680
+ /** Optional note for the before photo */
1682
1681
  beforeNote?: string | null;
1682
+ /** Optional note for the after photo */
1683
+ afterNote?: string | null;
1684
+ /** Whether this photo pair (before AND after) should be visible to the patient */
1685
+ showToPatient?: boolean;
1686
+ /** Whether the before note should be visible to the patient */
1687
+ beforeNoteVisibleToPatient?: boolean;
1688
+ /** Whether the after note should be visible to the patient */
1689
+ afterNoteVisibleToPatient?: boolean;
1690
+ /** Timestamp when visibility was last updated */
1691
+ visibilityUpdatedAt?: Timestamp;
1692
+ /** ID of the doctor who last updated visibility */
1693
+ visibilityUpdatedBy?: string;
1683
1694
  }
1684
1695
  /**
1685
1696
  * Interface for zone item data (products or notes per zone)
@@ -1786,7 +1797,14 @@ interface AppointmentMetadata {
1786
1797
  extendedProcedures?: ExtendedProcedureInfo[];
1787
1798
  recommendedProcedures: RecommendedProcedure[];
1788
1799
  finalbilling: FinalBilling | null;
1789
- finalizationNotes: string | null;
1800
+ /** Final treatment notes shared with patient */
1801
+ finalizationNotesShared?: string | null;
1802
+ /** Final treatment notes for internal use only (not shared with patient) */
1803
+ finalizationNotesInternal?: string | null;
1804
+ /**
1805
+ * @deprecated Use finalizationNotesShared instead. Kept for backward compatibility during migration.
1806
+ */
1807
+ finalizationNotes?: string | null;
1790
1808
  /**
1791
1809
  * @deprecated Use zonesData instead
1792
1810
  */
package/dist/index.d.mts CHANGED
@@ -5604,9 +5604,20 @@ interface BeforeAfterPerZone {
5604
5604
  before: MediaResource | null;
5605
5605
  /** URL for after photo or null if not available */
5606
5606
  after: MediaResource | null;
5607
- /** Optional note for the zone */
5608
- afterNote?: string | null;
5607
+ /** Optional note for the before photo */
5609
5608
  beforeNote?: string | null;
5609
+ /** Optional note for the after photo */
5610
+ afterNote?: string | null;
5611
+ /** Whether this photo pair (before AND after) should be visible to the patient */
5612
+ showToPatient?: boolean;
5613
+ /** Whether the before note should be visible to the patient */
5614
+ beforeNoteVisibleToPatient?: boolean;
5615
+ /** Whether the after note should be visible to the patient */
5616
+ afterNoteVisibleToPatient?: boolean;
5617
+ /** Timestamp when visibility was last updated */
5618
+ visibilityUpdatedAt?: Timestamp;
5619
+ /** ID of the doctor who last updated visibility */
5620
+ visibilityUpdatedBy?: string;
5610
5621
  }
5611
5622
  /**
5612
5623
  * Interface for zone photo upload data
@@ -5723,7 +5734,14 @@ interface AppointmentMetadata {
5723
5734
  extendedProcedures?: ExtendedProcedureInfo[];
5724
5735
  recommendedProcedures: RecommendedProcedure[];
5725
5736
  finalbilling: FinalBilling | null;
5726
- finalizationNotes: string | null;
5737
+ /** Final treatment notes shared with patient */
5738
+ finalizationNotesShared?: string | null;
5739
+ /** Final treatment notes for internal use only (not shared with patient) */
5740
+ finalizationNotesInternal?: string | null;
5741
+ /**
5742
+ * @deprecated Use finalizationNotesShared instead. Kept for backward compatibility during migration.
5743
+ */
5744
+ finalizationNotes?: string | null;
5727
5745
  /**
5728
5746
  * @deprecated Use zonesData instead
5729
5747
  */
@@ -7694,6 +7712,29 @@ declare class AppointmentService extends BaseService {
7694
7712
  * @returns The updated appointment
7695
7713
  */
7696
7714
  updateZonePhotoNotes(appointmentId: string, zoneId: string, photoIndex: number, beforeNote?: string, afterNote?: string): Promise<Appointment>;
7715
+ /**
7716
+ * Updates visibility of a photo pair (before AND after together)
7717
+ *
7718
+ * @param appointmentId ID of the appointment
7719
+ * @param zoneId Zone ID
7720
+ * @param photoIndex Index of the photo entry
7721
+ * @param showToPatient Whether the photo pair should be visible to patient
7722
+ * @param doctorId ID of the doctor making the change (for audit trail)
7723
+ * @returns The updated appointment
7724
+ */
7725
+ updateZonePhotoVisibility(appointmentId: string, zoneId: string, photoIndex: number, showToPatient: boolean, doctorId: string): Promise<Appointment>;
7726
+ /**
7727
+ * Updates visibility of a photo note (before or after)
7728
+ *
7729
+ * @param appointmentId ID of the appointment
7730
+ * @param zoneId Zone ID
7731
+ * @param photoIndex Index of the photo entry
7732
+ * @param noteType Type of note ('before' or 'after')
7733
+ * @param visibleToPatient Whether the note should be visible to patient
7734
+ * @param doctorId ID of the doctor making the change (for audit trail)
7735
+ * @returns The updated appointment
7736
+ */
7737
+ updateZonePhotoNoteVisibility(appointmentId: string, zoneId: string, photoIndex: number, noteType: 'before' | 'after', visibleToPatient: boolean, doctorId: string): Promise<Appointment>;
7697
7738
  /**
7698
7739
  * Gets a specific photo entry from a zone
7699
7740
  *
@@ -7703,6 +7744,15 @@ declare class AppointmentService extends BaseService {
7703
7744
  * @returns Photo entry
7704
7745
  */
7705
7746
  getZonePhotoEntry(appointmentId: string, zoneId: string, photoIndex: number): Promise<BeforeAfterPerZone>;
7747
+ /**
7748
+ * Updates finalization notes (shared with patient and/or internal only)
7749
+ *
7750
+ * @param appointmentId ID of the appointment
7751
+ * @param sharedNotes Notes to be shared with patient (optional)
7752
+ * @param internalNotes Notes for internal use only (optional)
7753
+ * @returns The updated appointment
7754
+ */
7755
+ updateFinalizationNotes(appointmentId: string, sharedNotes?: string | null, internalNotes?: string | null): Promise<Appointment>;
7706
7756
  /**
7707
7757
  * Gets all next steps recommendations for a patient from their past appointments.
7708
7758
  * Returns recommendations with context about which appointment, practitioner, and clinic suggested them.
package/dist/index.d.ts CHANGED
@@ -5604,9 +5604,20 @@ interface BeforeAfterPerZone {
5604
5604
  before: MediaResource | null;
5605
5605
  /** URL for after photo or null if not available */
5606
5606
  after: MediaResource | null;
5607
- /** Optional note for the zone */
5608
- afterNote?: string | null;
5607
+ /** Optional note for the before photo */
5609
5608
  beforeNote?: string | null;
5609
+ /** Optional note for the after photo */
5610
+ afterNote?: string | null;
5611
+ /** Whether this photo pair (before AND after) should be visible to the patient */
5612
+ showToPatient?: boolean;
5613
+ /** Whether the before note should be visible to the patient */
5614
+ beforeNoteVisibleToPatient?: boolean;
5615
+ /** Whether the after note should be visible to the patient */
5616
+ afterNoteVisibleToPatient?: boolean;
5617
+ /** Timestamp when visibility was last updated */
5618
+ visibilityUpdatedAt?: Timestamp;
5619
+ /** ID of the doctor who last updated visibility */
5620
+ visibilityUpdatedBy?: string;
5610
5621
  }
5611
5622
  /**
5612
5623
  * Interface for zone photo upload data
@@ -5723,7 +5734,14 @@ interface AppointmentMetadata {
5723
5734
  extendedProcedures?: ExtendedProcedureInfo[];
5724
5735
  recommendedProcedures: RecommendedProcedure[];
5725
5736
  finalbilling: FinalBilling | null;
5726
- finalizationNotes: string | null;
5737
+ /** Final treatment notes shared with patient */
5738
+ finalizationNotesShared?: string | null;
5739
+ /** Final treatment notes for internal use only (not shared with patient) */
5740
+ finalizationNotesInternal?: string | null;
5741
+ /**
5742
+ * @deprecated Use finalizationNotesShared instead. Kept for backward compatibility during migration.
5743
+ */
5744
+ finalizationNotes?: string | null;
5727
5745
  /**
5728
5746
  * @deprecated Use zonesData instead
5729
5747
  */
@@ -7694,6 +7712,29 @@ declare class AppointmentService extends BaseService {
7694
7712
  * @returns The updated appointment
7695
7713
  */
7696
7714
  updateZonePhotoNotes(appointmentId: string, zoneId: string, photoIndex: number, beforeNote?: string, afterNote?: string): Promise<Appointment>;
7715
+ /**
7716
+ * Updates visibility of a photo pair (before AND after together)
7717
+ *
7718
+ * @param appointmentId ID of the appointment
7719
+ * @param zoneId Zone ID
7720
+ * @param photoIndex Index of the photo entry
7721
+ * @param showToPatient Whether the photo pair should be visible to patient
7722
+ * @param doctorId ID of the doctor making the change (for audit trail)
7723
+ * @returns The updated appointment
7724
+ */
7725
+ updateZonePhotoVisibility(appointmentId: string, zoneId: string, photoIndex: number, showToPatient: boolean, doctorId: string): Promise<Appointment>;
7726
+ /**
7727
+ * Updates visibility of a photo note (before or after)
7728
+ *
7729
+ * @param appointmentId ID of the appointment
7730
+ * @param zoneId Zone ID
7731
+ * @param photoIndex Index of the photo entry
7732
+ * @param noteType Type of note ('before' or 'after')
7733
+ * @param visibleToPatient Whether the note should be visible to patient
7734
+ * @param doctorId ID of the doctor making the change (for audit trail)
7735
+ * @returns The updated appointment
7736
+ */
7737
+ updateZonePhotoNoteVisibility(appointmentId: string, zoneId: string, photoIndex: number, noteType: 'before' | 'after', visibleToPatient: boolean, doctorId: string): Promise<Appointment>;
7697
7738
  /**
7698
7739
  * Gets a specific photo entry from a zone
7699
7740
  *
@@ -7703,6 +7744,15 @@ declare class AppointmentService extends BaseService {
7703
7744
  * @returns Photo entry
7704
7745
  */
7705
7746
  getZonePhotoEntry(appointmentId: string, zoneId: string, photoIndex: number): Promise<BeforeAfterPerZone>;
7747
+ /**
7748
+ * Updates finalization notes (shared with patient and/or internal only)
7749
+ *
7750
+ * @param appointmentId ID of the appointment
7751
+ * @param sharedNotes Notes to be shared with patient (optional)
7752
+ * @param internalNotes Notes for internal use only (optional)
7753
+ * @returns The updated appointment
7754
+ */
7755
+ updateFinalizationNotes(appointmentId: string, sharedNotes?: string | null, internalNotes?: string | null): Promise<Appointment>;
7706
7756
  /**
7707
7757
  * Gets all next steps recommendations for a patient from their past appointments.
7708
7758
  * Returns recommendations with context about which appointment, practitioner, and clinic suggested them.
package/dist/index.js CHANGED
@@ -3903,8 +3903,14 @@ var finalizedDetailsSchema = import_zod3.z.object({
3903
3903
  var beforeAfterPerZoneSchema = import_zod3.z.object({
3904
3904
  before: mediaResourceSchema.nullable(),
3905
3905
  after: mediaResourceSchema.nullable(),
3906
+ beforeNote: import_zod3.z.string().nullable().optional(),
3906
3907
  afterNote: import_zod3.z.string().nullable().optional(),
3907
- beforeNote: import_zod3.z.string().nullable().optional()
3908
+ showToPatient: import_zod3.z.boolean().optional().default(false),
3909
+ beforeNoteVisibleToPatient: import_zod3.z.boolean().optional().default(false),
3910
+ afterNoteVisibleToPatient: import_zod3.z.boolean().optional().default(false),
3911
+ visibilityUpdatedAt: import_zod3.z.any().optional(),
3912
+ // Timestamp
3913
+ visibilityUpdatedBy: import_zod3.z.string().optional()
3908
3914
  });
3909
3915
  var billingPerZoneSchema = import_zod3.z.object({
3910
3916
  Product: import_zod3.z.string().min(MIN_STRING_LENGTH, "Product name is required"),
@@ -3962,6 +3968,7 @@ var zoneItemDataSchema = import_zod3.z.object({
3962
3968
  }
3963
3969
  ),
3964
3970
  notes: import_zod3.z.string().max(MAX_STRING_LENGTH_LONG, "Notes too long").optional(),
3971
+ notesVisibleToPatient: import_zod3.z.boolean().optional().default(false),
3965
3972
  subtotal: import_zod3.z.number().min(0, "Subtotal must be non-negative").optional(),
3966
3973
  ionNumber: import_zod3.z.string().optional(),
3967
3974
  createdAt: import_zod3.z.string().optional(),
@@ -4025,7 +4032,10 @@ var appointmentMetadataSchema = import_zod3.z.object({
4025
4032
  recommendedProcedures: import_zod3.z.array(recommendedProcedureSchema).optional().default([]),
4026
4033
  zoneBilling: import_zod3.z.record(import_zod3.z.string(), billingPerZoneSchema).nullable().optional(),
4027
4034
  finalbilling: finalBillingSchema.nullable(),
4028
- finalizationNotes: import_zod3.z.string().nullable()
4035
+ finalizationNotesShared: import_zod3.z.string().nullable().optional(),
4036
+ finalizationNotesInternal: import_zod3.z.string().nullable().optional(),
4037
+ finalizationNotes: import_zod3.z.string().nullable().optional()
4038
+ // @deprecated - kept for backward compatibility
4029
4039
  });
4030
4040
  var createAppointmentSchema = import_zod3.z.object({
4031
4041
  clinicBranchId: import_zod3.z.string().min(MIN_STRING_LENGTH, "Clinic branch ID is required"),
@@ -4826,10 +4836,14 @@ function initializeMetadata(appointment) {
4826
4836
  extendedProcedures: [],
4827
4837
  recommendedProcedures: [],
4828
4838
  finalbilling: null,
4839
+ finalizationNotesShared: null,
4840
+ finalizationNotesInternal: null,
4829
4841
  finalizationNotes: null
4842
+ // @deprecated - kept for backward compatibility
4830
4843
  };
4831
4844
  }
4832
4845
  async function addItemToZoneUtil(db, appointmentId, zoneId, item) {
4846
+ var _a;
4833
4847
  validateZoneKeyFormat(zoneId);
4834
4848
  const appointment = await getAppointmentOrThrow(db, appointmentId);
4835
4849
  const metadata = initializeMetadata(appointment);
@@ -4843,6 +4857,8 @@ async function addItemToZoneUtil(db, appointmentId, zoneId, item) {
4843
4857
  parentZone: zoneId,
4844
4858
  // Set parentZone to the zone key
4845
4859
  subtotal: calculateItemSubtotal(item),
4860
+ // Set default visibility to false (privacy-first) if notes exist and visibility not explicitly set
4861
+ notesVisibleToPatient: (_a = item.notesVisibleToPatient) != null ? _a : item.notes ? false : void 0,
4846
4862
  createdAt: now,
4847
4863
  updatedAt: now
4848
4864
  };
@@ -5342,7 +5358,17 @@ async function getRecommendedProceduresUtil(db, appointmentId) {
5342
5358
 
5343
5359
  // src/services/appointment/utils/zone-photo.utils.ts
5344
5360
  var import_firestore13 = require("firebase/firestore");
5345
- async function updateZonePhotoEntryUtil(db, appointmentId, zoneId, photoIndex, updates) {
5361
+ function addVisibilityAudit(updates, doctorId) {
5362
+ if (updates.showToPatient !== void 0 || updates.beforeNoteVisibleToPatient !== void 0 || updates.afterNoteVisibleToPatient !== void 0) {
5363
+ return {
5364
+ ...updates,
5365
+ visibilityUpdatedAt: (0, import_firestore13.serverTimestamp)(),
5366
+ visibilityUpdatedBy: doctorId
5367
+ };
5368
+ }
5369
+ return updates;
5370
+ }
5371
+ async function updateZonePhotoEntryUtil(db, appointmentId, zoneId, photoIndex, updates, doctorId) {
5346
5372
  var _a;
5347
5373
  const appointment = await getAppointmentOrThrow(db, appointmentId);
5348
5374
  const zonePhotos = (_a = appointment.metadata) == null ? void 0 : _a.zonePhotos;
@@ -5353,11 +5379,12 @@ async function updateZonePhotoEntryUtil(db, appointmentId, zoneId, photoIndex, u
5353
5379
  if (photoIndex < 0 || photoIndex >= zoneArray.length) {
5354
5380
  throw new Error(`Invalid photo index ${photoIndex} for zone ${zoneId}. Must be between 0 and ${zoneArray.length - 1}`);
5355
5381
  }
5382
+ const updatesWithAudit = doctorId ? addVisibilityAudit(updates, doctorId) : updates;
5356
5383
  const updatedZonePhotos = { ...zonePhotos };
5357
5384
  updatedZonePhotos[zoneId] = [...zoneArray];
5358
5385
  updatedZonePhotos[zoneId][photoIndex] = {
5359
5386
  ...zoneArray[photoIndex],
5360
- ...updates
5387
+ ...updatesWithAudit
5361
5388
  };
5362
5389
  const appointmentRef = (0, import_firestore13.doc)(db, APPOINTMENTS_COLLECTION, appointmentId);
5363
5390
  await (0, import_firestore13.updateDoc)(appointmentRef, {
@@ -5401,6 +5428,20 @@ async function getZonePhotoEntryUtil(db, appointmentId, zoneId, photoIndex) {
5401
5428
  }
5402
5429
  return zoneArray[photoIndex];
5403
5430
  }
5431
+ async function updateZonePhotoVisibilityUtil(db, appointmentId, zoneId, photoIndex, showToPatient, doctorId) {
5432
+ return updateZonePhotoEntryUtil(
5433
+ db,
5434
+ appointmentId,
5435
+ zoneId,
5436
+ photoIndex,
5437
+ { showToPatient },
5438
+ doctorId
5439
+ );
5440
+ }
5441
+ async function updateZonePhotoNoteVisibilityUtil(db, appointmentId, zoneId, photoIndex, noteType, visibleToPatient, doctorId) {
5442
+ const updates = noteType === "before" ? { beforeNoteVisibleToPatient: visibleToPatient } : { afterNoteVisibleToPatient: visibleToPatient };
5443
+ return updateZonePhotoEntryUtil(db, appointmentId, zoneId, photoIndex, updates, doctorId);
5444
+ }
5404
5445
 
5405
5446
  // src/services/appointment/appointment.service.ts
5406
5447
  var AppointmentService = class extends BaseService {
@@ -6267,6 +6308,7 @@ var AppointmentService = class extends BaseService {
6267
6308
  * @returns The updated appointment
6268
6309
  */
6269
6310
  async updateAppointmentZonePhoto(appointmentId, zoneId, photoType, mediaMetadata, notes) {
6311
+ var _a, _b, _c, _d;
6270
6312
  try {
6271
6313
  console.log(
6272
6314
  `[APPOINTMENT_SERVICE] Updating appointment metadata for ${photoType} photo in zone ${zoneId}`
@@ -6284,7 +6326,10 @@ var AppointmentService = class extends BaseService {
6284
6326
  recommendedProcedures: [],
6285
6327
  zoneBilling: null,
6286
6328
  finalbilling: null,
6329
+ finalizationNotesShared: null,
6330
+ finalizationNotesInternal: null,
6287
6331
  finalizationNotes: null
6332
+ // @deprecated - kept for backward compatibility
6288
6333
  };
6289
6334
  let currentZonePhotos = {};
6290
6335
  if (currentMetadata.zonePhotos) {
@@ -6299,7 +6344,11 @@ var AppointmentService = class extends BaseService {
6299
6344
  before: oldData.before || null,
6300
6345
  after: oldData.after || null,
6301
6346
  beforeNote: null,
6302
- afterNote: null
6347
+ afterNote: null,
6348
+ showToPatient: false,
6349
+ // Default: not visible to patient (privacy-first)
6350
+ beforeNoteVisibleToPatient: false,
6351
+ afterNoteVisibleToPatient: false
6303
6352
  }
6304
6353
  ];
6305
6354
  }
@@ -6312,7 +6361,13 @@ var AppointmentService = class extends BaseService {
6312
6361
  before: photoType === "before" ? mediaMetadata.url : null,
6313
6362
  after: photoType === "after" ? mediaMetadata.url : null,
6314
6363
  beforeNote: photoType === "before" ? notes || null : null,
6315
- afterNote: photoType === "after" ? notes || null : null
6364
+ afterNote: photoType === "after" ? notes || null : null,
6365
+ showToPatient: false,
6366
+ // Default: not visible to patient
6367
+ beforeNoteVisibleToPatient: false,
6368
+ // Default: not visible to patient
6369
+ afterNoteVisibleToPatient: false
6370
+ // Default: not visible to patient
6316
6371
  };
6317
6372
  currentZonePhotos[zoneId] = [...currentZonePhotos[zoneId], newEntry];
6318
6373
  if (currentZonePhotos[zoneId].length > 10) {
@@ -6331,7 +6386,10 @@ var AppointmentService = class extends BaseService {
6331
6386
  zoneBilling: currentMetadata.zoneBilling
6332
6387
  },
6333
6388
  finalbilling: currentMetadata.finalbilling,
6334
- finalizationNotes: currentMetadata.finalizationNotes
6389
+ finalizationNotesShared: (_a = currentMetadata.finalizationNotesShared) != null ? _a : null,
6390
+ finalizationNotesInternal: (_b = currentMetadata.finalizationNotesInternal) != null ? _b : null,
6391
+ finalizationNotes: (_d = (_c = currentMetadata.finalizationNotes) != null ? _c : currentMetadata.finalizationNotesShared) != null ? _d : null
6392
+ // @deprecated - migrate from old field if exists
6335
6393
  },
6336
6394
  updatedAt: (0, import_firestore14.serverTimestamp)()
6337
6395
  };
@@ -6385,7 +6443,7 @@ var AppointmentService = class extends BaseService {
6385
6443
  * @returns The updated appointment
6386
6444
  */
6387
6445
  async deleteZonePhoto(appointmentId, zoneId, photoIndex) {
6388
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
6446
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
6389
6447
  try {
6390
6448
  console.log(
6391
6449
  `[APPOINTMENT_SERVICE] Deleting zone photo index ${photoIndex} for zone ${zoneId} in appointment ${appointmentId}`
@@ -6442,7 +6500,10 @@ var AppointmentService = class extends BaseService {
6442
6500
  zoneBilling: appointment.metadata.zoneBilling
6443
6501
  },
6444
6502
  finalbilling: ((_h = appointment.metadata) == null ? void 0 : _h.finalbilling) || null,
6445
- finalizationNotes: ((_i = appointment.metadata) == null ? void 0 : _i.finalizationNotes) || null
6503
+ finalizationNotesShared: (_l = (_k = (_i = appointment.metadata) == null ? void 0 : _i.finalizationNotesShared) != null ? _k : (_j = appointment.metadata) == null ? void 0 : _j.finalizationNotes) != null ? _l : null,
6504
+ finalizationNotesInternal: (_n = (_m = appointment.metadata) == null ? void 0 : _m.finalizationNotesInternal) != null ? _n : null,
6505
+ finalizationNotes: (_p = (_o = appointment.metadata) == null ? void 0 : _o.finalizationNotes) != null ? _p : null
6506
+ // @deprecated
6446
6507
  },
6447
6508
  updatedAt: (0, import_firestore14.serverTimestamp)()
6448
6509
  };
@@ -6641,7 +6702,7 @@ var AppointmentService = class extends BaseService {
6641
6702
  * @returns The updated appointment with recalculated billing
6642
6703
  */
6643
6704
  async recalculateFinalBilling(appointmentId, taxRate) {
6644
- var _a;
6705
+ var _a, _b, _c, _d, _e;
6645
6706
  try {
6646
6707
  console.log(
6647
6708
  `[APPOINTMENT_SERVICE] Recalculating final billing for appointment ${appointmentId}`
@@ -6663,7 +6724,10 @@ var AppointmentService = class extends BaseService {
6663
6724
  extendedProcedures: [],
6664
6725
  recommendedProcedures: [],
6665
6726
  finalbilling: null,
6727
+ finalizationNotesShared: null,
6728
+ finalizationNotesInternal: null,
6666
6729
  finalizationNotes: null
6730
+ // @deprecated
6667
6731
  };
6668
6732
  const shouldUpdatePaymentStatus = finalbilling.finalPrice > 0 && appointment.paymentStatus === "not_applicable" /* NOT_APPLICABLE */;
6669
6733
  const updateData = {
@@ -6679,7 +6743,10 @@ var AppointmentService = class extends BaseService {
6679
6743
  zoneBilling: currentMetadata.zoneBilling
6680
6744
  },
6681
6745
  finalbilling,
6682
- finalizationNotes: currentMetadata.finalizationNotes
6746
+ finalizationNotesShared: (_b = currentMetadata.finalizationNotesShared) != null ? _b : null,
6747
+ finalizationNotesInternal: (_c = currentMetadata.finalizationNotesInternal) != null ? _c : null,
6748
+ finalizationNotes: (_e = (_d = currentMetadata.finalizationNotes) != null ? _d : currentMetadata.finalizationNotesShared) != null ? _e : null
6749
+ // @deprecated
6683
6750
  },
6684
6751
  ...shouldUpdatePaymentStatus && {
6685
6752
  paymentStatus: "unpaid" /* UNPAID */
@@ -6879,6 +6946,64 @@ var AppointmentService = class extends BaseService {
6879
6946
  throw error;
6880
6947
  }
6881
6948
  }
6949
+ /**
6950
+ * Updates visibility of a photo pair (before AND after together)
6951
+ *
6952
+ * @param appointmentId ID of the appointment
6953
+ * @param zoneId Zone ID
6954
+ * @param photoIndex Index of the photo entry
6955
+ * @param showToPatient Whether the photo pair should be visible to patient
6956
+ * @param doctorId ID of the doctor making the change (for audit trail)
6957
+ * @returns The updated appointment
6958
+ */
6959
+ async updateZonePhotoVisibility(appointmentId, zoneId, photoIndex, showToPatient, doctorId) {
6960
+ try {
6961
+ console.log(
6962
+ `[APPOINTMENT_SERVICE] Updating photo visibility at index ${photoIndex} for zone ${zoneId} to ${showToPatient}`
6963
+ );
6964
+ return await updateZonePhotoVisibilityUtil(
6965
+ this.db,
6966
+ appointmentId,
6967
+ zoneId,
6968
+ photoIndex,
6969
+ showToPatient,
6970
+ doctorId
6971
+ );
6972
+ } catch (error) {
6973
+ console.error(`[APPOINTMENT_SERVICE] Error updating zone photo visibility:`, error);
6974
+ throw error;
6975
+ }
6976
+ }
6977
+ /**
6978
+ * Updates visibility of a photo note (before or after)
6979
+ *
6980
+ * @param appointmentId ID of the appointment
6981
+ * @param zoneId Zone ID
6982
+ * @param photoIndex Index of the photo entry
6983
+ * @param noteType Type of note ('before' or 'after')
6984
+ * @param visibleToPatient Whether the note should be visible to patient
6985
+ * @param doctorId ID of the doctor making the change (for audit trail)
6986
+ * @returns The updated appointment
6987
+ */
6988
+ async updateZonePhotoNoteVisibility(appointmentId, zoneId, photoIndex, noteType, visibleToPatient, doctorId) {
6989
+ try {
6990
+ console.log(
6991
+ `[APPOINTMENT_SERVICE] Updating ${noteType} note visibility at index ${photoIndex} for zone ${zoneId} to ${visibleToPatient}`
6992
+ );
6993
+ return await updateZonePhotoNoteVisibilityUtil(
6994
+ this.db,
6995
+ appointmentId,
6996
+ zoneId,
6997
+ photoIndex,
6998
+ noteType,
6999
+ visibleToPatient,
7000
+ doctorId
7001
+ );
7002
+ } catch (error) {
7003
+ console.error(`[APPOINTMENT_SERVICE] Error updating zone photo note visibility:`, error);
7004
+ throw error;
7005
+ }
7006
+ }
6882
7007
  /**
6883
7008
  * Gets a specific photo entry from a zone
6884
7009
  *
@@ -6898,6 +7023,54 @@ var AppointmentService = class extends BaseService {
6898
7023
  throw error;
6899
7024
  }
6900
7025
  }
7026
+ /**
7027
+ * Updates finalization notes (shared with patient and/or internal only)
7028
+ *
7029
+ * @param appointmentId ID of the appointment
7030
+ * @param sharedNotes Notes to be shared with patient (optional)
7031
+ * @param internalNotes Notes for internal use only (optional)
7032
+ * @returns The updated appointment
7033
+ */
7034
+ async updateFinalizationNotes(appointmentId, sharedNotes, internalNotes) {
7035
+ try {
7036
+ const appointment = await this.getAppointmentById(appointmentId);
7037
+ if (!appointment) {
7038
+ throw new Error(`Appointment ${appointmentId} not found`);
7039
+ }
7040
+ const currentMetadata = appointment.metadata || {
7041
+ selectedZones: null,
7042
+ zonePhotos: null,
7043
+ zonesData: null,
7044
+ appointmentProducts: [],
7045
+ extendedProcedures: [],
7046
+ recommendedProcedures: [],
7047
+ finalbilling: null,
7048
+ finalizationNotesShared: null,
7049
+ finalizationNotesInternal: null,
7050
+ finalizationNotes: null
7051
+ };
7052
+ const updateData = {
7053
+ metadata: {
7054
+ selectedZones: currentMetadata.selectedZones,
7055
+ zonePhotos: currentMetadata.zonePhotos,
7056
+ zonesData: currentMetadata.zonesData || null,
7057
+ appointmentProducts: currentMetadata.appointmentProducts || [],
7058
+ extendedProcedures: currentMetadata.extendedProcedures || [],
7059
+ recommendedProcedures: currentMetadata.recommendedProcedures || [],
7060
+ finalbilling: currentMetadata.finalbilling,
7061
+ finalizationNotesShared: sharedNotes !== void 0 ? sharedNotes : currentMetadata.finalizationNotesShared,
7062
+ finalizationNotesInternal: internalNotes !== void 0 ? internalNotes : currentMetadata.finalizationNotesInternal,
7063
+ // Keep deprecated field for backward compatibility during migration
7064
+ finalizationNotes: sharedNotes !== void 0 ? sharedNotes : currentMetadata.finalizationNotes || currentMetadata.finalizationNotesShared
7065
+ },
7066
+ updatedAt: (0, import_firestore14.serverTimestamp)()
7067
+ };
7068
+ return await this.updateAppointment(appointmentId, updateData);
7069
+ } catch (error) {
7070
+ console.error(`[APPOINTMENT_SERVICE] Error updating finalization notes:`, error);
7071
+ throw error;
7072
+ }
7073
+ }
6901
7074
  /**
6902
7075
  * Gets all next steps recommendations for a patient from their past appointments.
6903
7076
  * Returns recommendations with context about which appointment, practitioner, and clinic suggested them.