@blackcode_sa/metaestetics-api 1.14.44 → 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)
@@ -1702,8 +1713,6 @@ interface ZoneItemData {
1702
1713
  notes?: string;
1703
1714
  subtotal?: number;
1704
1715
  ionNumber?: string;
1705
- lotNumber?: string;
1706
- expiryDate?: string;
1707
1716
  createdAt?: string;
1708
1717
  updatedAt?: string;
1709
1718
  }
@@ -1788,7 +1797,14 @@ interface AppointmentMetadata {
1788
1797
  extendedProcedures?: ExtendedProcedureInfo[];
1789
1798
  recommendedProcedures: RecommendedProcedure[];
1790
1799
  finalbilling: FinalBilling | null;
1791
- 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;
1792
1808
  /**
1793
1809
  * @deprecated Use zonesData instead
1794
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)
@@ -1702,8 +1713,6 @@ interface ZoneItemData {
1702
1713
  notes?: string;
1703
1714
  subtotal?: number;
1704
1715
  ionNumber?: string;
1705
- lotNumber?: string;
1706
- expiryDate?: string;
1707
1716
  createdAt?: string;
1708
1717
  updatedAt?: string;
1709
1718
  }
@@ -1788,7 +1797,14 @@ interface AppointmentMetadata {
1788
1797
  extendedProcedures?: ExtendedProcedureInfo[];
1789
1798
  recommendedProcedures: RecommendedProcedure[];
1790
1799
  finalbilling: FinalBilling | null;
1791
- 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;
1792
1808
  /**
1793
1809
  * @deprecated Use zonesData instead
1794
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
@@ -5639,8 +5650,6 @@ interface ZoneItemData {
5639
5650
  notes?: string;
5640
5651
  subtotal?: number;
5641
5652
  ionNumber?: string;
5642
- lotNumber?: string;
5643
- expiryDate?: string;
5644
5653
  createdAt?: string;
5645
5654
  updatedAt?: string;
5646
5655
  }
@@ -5725,7 +5734,14 @@ interface AppointmentMetadata {
5725
5734
  extendedProcedures?: ExtendedProcedureInfo[];
5726
5735
  recommendedProcedures: RecommendedProcedure[];
5727
5736
  finalbilling: FinalBilling | null;
5728
- 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;
5729
5745
  /**
5730
5746
  * @deprecated Use zonesData instead
5731
5747
  */
@@ -7696,6 +7712,29 @@ declare class AppointmentService extends BaseService {
7696
7712
  * @returns The updated appointment
7697
7713
  */
7698
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>;
7699
7738
  /**
7700
7739
  * Gets a specific photo entry from a zone
7701
7740
  *
@@ -7705,6 +7744,15 @@ declare class AppointmentService extends BaseService {
7705
7744
  * @returns Photo entry
7706
7745
  */
7707
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>;
7708
7756
  /**
7709
7757
  * Gets all next steps recommendations for a patient from their past appointments.
7710
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
@@ -5639,8 +5650,6 @@ interface ZoneItemData {
5639
5650
  notes?: string;
5640
5651
  subtotal?: number;
5641
5652
  ionNumber?: string;
5642
- lotNumber?: string;
5643
- expiryDate?: string;
5644
5653
  createdAt?: string;
5645
5654
  updatedAt?: string;
5646
5655
  }
@@ -5725,7 +5734,14 @@ interface AppointmentMetadata {
5725
5734
  extendedProcedures?: ExtendedProcedureInfo[];
5726
5735
  recommendedProcedures: RecommendedProcedure[];
5727
5736
  finalbilling: FinalBilling | null;
5728
- 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;
5729
5745
  /**
5730
5746
  * @deprecated Use zonesData instead
5731
5747
  */
@@ -7696,6 +7712,29 @@ declare class AppointmentService extends BaseService {
7696
7712
  * @returns The updated appointment
7697
7713
  */
7698
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>;
7699
7738
  /**
7700
7739
  * Gets a specific photo entry from a zone
7701
7740
  *
@@ -7705,6 +7744,15 @@ declare class AppointmentService extends BaseService {
7705
7744
  * @returns Photo entry
7706
7745
  */
7707
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>;
7708
7756
  /**
7709
7757
  * Gets all next steps recommendations for a patient from their past appointments.
7710
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,11 +3968,9 @@ 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
- lotNumber: import_zod3.z.string().max(MAX_STRING_LENGTH, "Lot number too long").optional(),
3968
- expiryDate: import_zod3.z.string().optional(),
3969
- // ISO date string (YYYY-MM-DD format)
3970
3974
  createdAt: import_zod3.z.string().optional(),
3971
3975
  updatedAt: import_zod3.z.string().optional()
3972
3976
  }).refine(
@@ -4028,7 +4032,10 @@ var appointmentMetadataSchema = import_zod3.z.object({
4028
4032
  recommendedProcedures: import_zod3.z.array(recommendedProcedureSchema).optional().default([]),
4029
4033
  zoneBilling: import_zod3.z.record(import_zod3.z.string(), billingPerZoneSchema).nullable().optional(),
4030
4034
  finalbilling: finalBillingSchema.nullable(),
4031
- 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
4032
4039
  });
4033
4040
  var createAppointmentSchema = import_zod3.z.object({
4034
4041
  clinicBranchId: import_zod3.z.string().min(MIN_STRING_LENGTH, "Clinic branch ID is required"),
@@ -4829,10 +4836,14 @@ function initializeMetadata(appointment) {
4829
4836
  extendedProcedures: [],
4830
4837
  recommendedProcedures: [],
4831
4838
  finalbilling: null,
4839
+ finalizationNotesShared: null,
4840
+ finalizationNotesInternal: null,
4832
4841
  finalizationNotes: null
4842
+ // @deprecated - kept for backward compatibility
4833
4843
  };
4834
4844
  }
4835
4845
  async function addItemToZoneUtil(db, appointmentId, zoneId, item) {
4846
+ var _a;
4836
4847
  validateZoneKeyFormat(zoneId);
4837
4848
  const appointment = await getAppointmentOrThrow(db, appointmentId);
4838
4849
  const metadata = initializeMetadata(appointment);
@@ -4846,6 +4857,8 @@ async function addItemToZoneUtil(db, appointmentId, zoneId, item) {
4846
4857
  parentZone: zoneId,
4847
4858
  // Set parentZone to the zone key
4848
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,
4849
4862
  createdAt: now,
4850
4863
  updatedAt: now
4851
4864
  };
@@ -5345,7 +5358,17 @@ async function getRecommendedProceduresUtil(db, appointmentId) {
5345
5358
 
5346
5359
  // src/services/appointment/utils/zone-photo.utils.ts
5347
5360
  var import_firestore13 = require("firebase/firestore");
5348
- 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) {
5349
5372
  var _a;
5350
5373
  const appointment = await getAppointmentOrThrow(db, appointmentId);
5351
5374
  const zonePhotos = (_a = appointment.metadata) == null ? void 0 : _a.zonePhotos;
@@ -5356,11 +5379,12 @@ async function updateZonePhotoEntryUtil(db, appointmentId, zoneId, photoIndex, u
5356
5379
  if (photoIndex < 0 || photoIndex >= zoneArray.length) {
5357
5380
  throw new Error(`Invalid photo index ${photoIndex} for zone ${zoneId}. Must be between 0 and ${zoneArray.length - 1}`);
5358
5381
  }
5382
+ const updatesWithAudit = doctorId ? addVisibilityAudit(updates, doctorId) : updates;
5359
5383
  const updatedZonePhotos = { ...zonePhotos };
5360
5384
  updatedZonePhotos[zoneId] = [...zoneArray];
5361
5385
  updatedZonePhotos[zoneId][photoIndex] = {
5362
5386
  ...zoneArray[photoIndex],
5363
- ...updates
5387
+ ...updatesWithAudit
5364
5388
  };
5365
5389
  const appointmentRef = (0, import_firestore13.doc)(db, APPOINTMENTS_COLLECTION, appointmentId);
5366
5390
  await (0, import_firestore13.updateDoc)(appointmentRef, {
@@ -5404,6 +5428,20 @@ async function getZonePhotoEntryUtil(db, appointmentId, zoneId, photoIndex) {
5404
5428
  }
5405
5429
  return zoneArray[photoIndex];
5406
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
+ }
5407
5445
 
5408
5446
  // src/services/appointment/appointment.service.ts
5409
5447
  var AppointmentService = class extends BaseService {
@@ -6270,6 +6308,7 @@ var AppointmentService = class extends BaseService {
6270
6308
  * @returns The updated appointment
6271
6309
  */
6272
6310
  async updateAppointmentZonePhoto(appointmentId, zoneId, photoType, mediaMetadata, notes) {
6311
+ var _a, _b, _c, _d;
6273
6312
  try {
6274
6313
  console.log(
6275
6314
  `[APPOINTMENT_SERVICE] Updating appointment metadata for ${photoType} photo in zone ${zoneId}`
@@ -6287,7 +6326,10 @@ var AppointmentService = class extends BaseService {
6287
6326
  recommendedProcedures: [],
6288
6327
  zoneBilling: null,
6289
6328
  finalbilling: null,
6329
+ finalizationNotesShared: null,
6330
+ finalizationNotesInternal: null,
6290
6331
  finalizationNotes: null
6332
+ // @deprecated - kept for backward compatibility
6291
6333
  };
6292
6334
  let currentZonePhotos = {};
6293
6335
  if (currentMetadata.zonePhotos) {
@@ -6302,7 +6344,11 @@ var AppointmentService = class extends BaseService {
6302
6344
  before: oldData.before || null,
6303
6345
  after: oldData.after || null,
6304
6346
  beforeNote: null,
6305
- afterNote: null
6347
+ afterNote: null,
6348
+ showToPatient: false,
6349
+ // Default: not visible to patient (privacy-first)
6350
+ beforeNoteVisibleToPatient: false,
6351
+ afterNoteVisibleToPatient: false
6306
6352
  }
6307
6353
  ];
6308
6354
  }
@@ -6315,7 +6361,13 @@ var AppointmentService = class extends BaseService {
6315
6361
  before: photoType === "before" ? mediaMetadata.url : null,
6316
6362
  after: photoType === "after" ? mediaMetadata.url : null,
6317
6363
  beforeNote: photoType === "before" ? notes || null : null,
6318
- 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
6319
6371
  };
6320
6372
  currentZonePhotos[zoneId] = [...currentZonePhotos[zoneId], newEntry];
6321
6373
  if (currentZonePhotos[zoneId].length > 10) {
@@ -6334,7 +6386,10 @@ var AppointmentService = class extends BaseService {
6334
6386
  zoneBilling: currentMetadata.zoneBilling
6335
6387
  },
6336
6388
  finalbilling: currentMetadata.finalbilling,
6337
- 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
6338
6393
  },
6339
6394
  updatedAt: (0, import_firestore14.serverTimestamp)()
6340
6395
  };
@@ -6388,7 +6443,7 @@ var AppointmentService = class extends BaseService {
6388
6443
  * @returns The updated appointment
6389
6444
  */
6390
6445
  async deleteZonePhoto(appointmentId, zoneId, photoIndex) {
6391
- 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;
6392
6447
  try {
6393
6448
  console.log(
6394
6449
  `[APPOINTMENT_SERVICE] Deleting zone photo index ${photoIndex} for zone ${zoneId} in appointment ${appointmentId}`
@@ -6445,7 +6500,10 @@ var AppointmentService = class extends BaseService {
6445
6500
  zoneBilling: appointment.metadata.zoneBilling
6446
6501
  },
6447
6502
  finalbilling: ((_h = appointment.metadata) == null ? void 0 : _h.finalbilling) || null,
6448
- 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
6449
6507
  },
6450
6508
  updatedAt: (0, import_firestore14.serverTimestamp)()
6451
6509
  };
@@ -6644,7 +6702,7 @@ var AppointmentService = class extends BaseService {
6644
6702
  * @returns The updated appointment with recalculated billing
6645
6703
  */
6646
6704
  async recalculateFinalBilling(appointmentId, taxRate) {
6647
- var _a;
6705
+ var _a, _b, _c, _d, _e;
6648
6706
  try {
6649
6707
  console.log(
6650
6708
  `[APPOINTMENT_SERVICE] Recalculating final billing for appointment ${appointmentId}`
@@ -6666,7 +6724,10 @@ var AppointmentService = class extends BaseService {
6666
6724
  extendedProcedures: [],
6667
6725
  recommendedProcedures: [],
6668
6726
  finalbilling: null,
6727
+ finalizationNotesShared: null,
6728
+ finalizationNotesInternal: null,
6669
6729
  finalizationNotes: null
6730
+ // @deprecated
6670
6731
  };
6671
6732
  const shouldUpdatePaymentStatus = finalbilling.finalPrice > 0 && appointment.paymentStatus === "not_applicable" /* NOT_APPLICABLE */;
6672
6733
  const updateData = {
@@ -6682,7 +6743,10 @@ var AppointmentService = class extends BaseService {
6682
6743
  zoneBilling: currentMetadata.zoneBilling
6683
6744
  },
6684
6745
  finalbilling,
6685
- 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
6686
6750
  },
6687
6751
  ...shouldUpdatePaymentStatus && {
6688
6752
  paymentStatus: "unpaid" /* UNPAID */
@@ -6882,6 +6946,64 @@ var AppointmentService = class extends BaseService {
6882
6946
  throw error;
6883
6947
  }
6884
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
+ }
6885
7007
  /**
6886
7008
  * Gets a specific photo entry from a zone
6887
7009
  *
@@ -6901,6 +7023,54 @@ var AppointmentService = class extends BaseService {
6901
7023
  throw error;
6902
7024
  }
6903
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
+ }
6904
7074
  /**
6905
7075
  * Gets all next steps recommendations for a patient from their past appointments.
6906
7076
  * Returns recommendations with context about which appointment, practitioner, and clinic suggested them.