@blackcode_sa/metaestetics-api 1.14.54 → 1.14.57

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.
@@ -1659,6 +1659,7 @@ interface LinkedFormInfo {
1659
1659
  path: string;
1660
1660
  submittedAt?: Timestamp;
1661
1661
  completedAt?: Timestamp;
1662
+ procedureId?: string;
1662
1663
  }
1663
1664
  /**
1664
1665
  * Interface for summarized patient review information linked to an appointment.
@@ -1713,8 +1714,8 @@ interface ZoneItemData {
1713
1714
  notes?: string;
1714
1715
  notesVisibleToPatient?: boolean;
1715
1716
  subtotal?: number;
1716
- ionNumber?: string;
1717
- expiryDate?: string;
1717
+ ionNumber?: string | null;
1718
+ expiryDate?: string | null;
1718
1719
  createdAt?: string;
1719
1720
  updatedAt?: string;
1720
1721
  }
@@ -1766,6 +1767,8 @@ interface AppointmentProductMetadata {
1766
1767
  interface ExtendedProcedureInfo {
1767
1768
  procedureId: string;
1768
1769
  procedureName: string;
1770
+ procedureDescription?: string;
1771
+ procedurePrice?: number;
1769
1772
  procedureFamily?: ProcedureFamily;
1770
1773
  procedureCategoryId: string;
1771
1774
  procedureCategoryName: string;
@@ -1659,6 +1659,7 @@ interface LinkedFormInfo {
1659
1659
  path: string;
1660
1660
  submittedAt?: Timestamp;
1661
1661
  completedAt?: Timestamp;
1662
+ procedureId?: string;
1662
1663
  }
1663
1664
  /**
1664
1665
  * Interface for summarized patient review information linked to an appointment.
@@ -1713,8 +1714,8 @@ interface ZoneItemData {
1713
1714
  notes?: string;
1714
1715
  notesVisibleToPatient?: boolean;
1715
1716
  subtotal?: number;
1716
- ionNumber?: string;
1717
- expiryDate?: string;
1717
+ ionNumber?: string | null;
1718
+ expiryDate?: string | null;
1718
1719
  createdAt?: string;
1719
1720
  updatedAt?: string;
1720
1721
  }
@@ -1766,6 +1767,8 @@ interface AppointmentProductMetadata {
1766
1767
  interface ExtendedProcedureInfo {
1767
1768
  procedureId: string;
1768
1769
  procedureName: string;
1770
+ procedureDescription?: string;
1771
+ procedurePrice?: number;
1769
1772
  procedureFamily?: ProcedureFamily;
1770
1773
  procedureCategoryId: string;
1771
1774
  procedureCategoryName: string;
package/dist/index.d.mts CHANGED
@@ -5586,6 +5586,7 @@ interface LinkedFormInfo {
5586
5586
  path: string;
5587
5587
  submittedAt?: Timestamp;
5588
5588
  completedAt?: Timestamp;
5589
+ procedureId?: string;
5589
5590
  }
5590
5591
  /**
5591
5592
  * Interface for summarized patient review information linked to an appointment.
@@ -5650,8 +5651,8 @@ interface ZoneItemData {
5650
5651
  notes?: string;
5651
5652
  notesVisibleToPatient?: boolean;
5652
5653
  subtotal?: number;
5653
- ionNumber?: string;
5654
- expiryDate?: string;
5654
+ ionNumber?: string | null;
5655
+ expiryDate?: string | null;
5655
5656
  createdAt?: string;
5656
5657
  updatedAt?: string;
5657
5658
  }
@@ -5703,6 +5704,8 @@ interface AppointmentProductMetadata {
5703
5704
  interface ExtendedProcedureInfo {
5704
5705
  procedureId: string;
5705
5706
  procedureName: string;
5707
+ procedureDescription?: string;
5708
+ procedurePrice?: number;
5706
5709
  procedureFamily?: ProcedureFamily;
5707
5710
  procedureCategoryId: string;
5708
5711
  procedureCategoryName: string;
package/dist/index.d.ts CHANGED
@@ -5586,6 +5586,7 @@ interface LinkedFormInfo {
5586
5586
  path: string;
5587
5587
  submittedAt?: Timestamp;
5588
5588
  completedAt?: Timestamp;
5589
+ procedureId?: string;
5589
5590
  }
5590
5591
  /**
5591
5592
  * Interface for summarized patient review information linked to an appointment.
@@ -5650,8 +5651,8 @@ interface ZoneItemData {
5650
5651
  notes?: string;
5651
5652
  notesVisibleToPatient?: boolean;
5652
5653
  subtotal?: number;
5653
- ionNumber?: string;
5654
- expiryDate?: string;
5654
+ ionNumber?: string | null;
5655
+ expiryDate?: string | null;
5655
5656
  createdAt?: string;
5656
5657
  updatedAt?: string;
5657
5658
  }
@@ -5703,6 +5704,8 @@ interface AppointmentProductMetadata {
5703
5704
  interface ExtendedProcedureInfo {
5704
5705
  procedureId: string;
5705
5706
  procedureName: string;
5707
+ procedureDescription?: string;
5708
+ procedurePrice?: number;
5706
5709
  procedureFamily?: ProcedureFamily;
5707
5710
  procedureCategoryId: string;
5708
5711
  procedureCategoryName: string;
package/dist/index.js CHANGED
@@ -3970,7 +3970,10 @@ var zoneItemDataSchema = import_zod3.z.object({
3970
3970
  notes: import_zod3.z.string().max(MAX_STRING_LENGTH_LONG, "Notes too long").optional(),
3971
3971
  notesVisibleToPatient: import_zod3.z.boolean().optional().default(false),
3972
3972
  subtotal: import_zod3.z.number().min(0, "Subtotal must be non-negative").optional(),
3973
- ionNumber: import_zod3.z.string().optional(),
3973
+ ionNumber: import_zod3.z.string().nullable().optional(),
3974
+ // Batch/Lot number - can be null to clear/delete
3975
+ expiryDate: import_zod3.z.string().nullable().optional(),
3976
+ // ISO date string (YYYY-MM-DD) - can be null to clear/delete
3974
3977
  createdAt: import_zod3.z.string().optional(),
3975
3978
  updatedAt: import_zod3.z.string().optional()
3976
3979
  }).refine(
@@ -4900,6 +4903,7 @@ async function removeItemFromZoneUtil(db, appointmentId, zoneId, itemIndex) {
4900
4903
  return getAppointmentOrThrow(db, appointmentId);
4901
4904
  }
4902
4905
  async function updateZoneItemUtil(db, appointmentId, zoneId, itemIndex, updates) {
4906
+ var _a, _b, _c, _d;
4903
4907
  validateZoneKeyFormat(zoneId);
4904
4908
  const appointment = await getAppointmentOrThrow(db, appointmentId);
4905
4909
  const metadata = initializeMetadata(appointment);
@@ -4910,17 +4914,37 @@ async function updateZoneItemUtil(db, appointmentId, zoneId, itemIndex, updates)
4910
4914
  if (itemIndex < 0 || itemIndex >= items.length) {
4911
4915
  throw new Error(`Invalid item index ${itemIndex} for zone ${zoneId}`);
4912
4916
  }
4917
+ const cleanUpdates = Object.fromEntries(
4918
+ Object.entries(updates).filter(([_, value]) => value !== void 0).map(([key, value]) => [
4919
+ key,
4920
+ value === "" ? null : value
4921
+ // Convert empty strings to null
4922
+ ])
4923
+ );
4924
+ console.log(`[updateZoneItemUtil] Updates received:`, {
4925
+ itemIndex,
4926
+ zoneId,
4927
+ rawUpdates: updates,
4928
+ cleanUpdates,
4929
+ hasIonNumber: "ionNumber" in cleanUpdates,
4930
+ hasExpiryDate: "expiryDate" in cleanUpdates,
4931
+ ionNumberValue: cleanUpdates.ionNumber,
4932
+ expiryDateValue: cleanUpdates.expiryDate
4933
+ });
4913
4934
  items[itemIndex] = {
4914
4935
  ...items[itemIndex],
4915
- ...updates,
4936
+ ...cleanUpdates,
4916
4937
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
4917
4938
  };
4918
- console.log(`[updateZoneItemUtil] BEFORE recalculation:`, {
4939
+ console.log(`[updateZoneItemUtil] Item after update:`, {
4919
4940
  itemIndex,
4941
+ ionNumber: items[itemIndex].ionNumber,
4942
+ expiryDate: items[itemIndex].expiryDate,
4920
4943
  quantity: items[itemIndex].quantity,
4921
4944
  priceOverrideAmount: items[itemIndex].priceOverrideAmount,
4922
4945
  price: items[itemIndex].price,
4923
- oldSubtotal: items[itemIndex].subtotal
4946
+ oldSubtotal: items[itemIndex].subtotal,
4947
+ allItemKeys: Object.keys(items[itemIndex])
4924
4948
  });
4925
4949
  items[itemIndex].subtotal = calculateItemSubtotal(items[itemIndex]);
4926
4950
  console.log(`[updateZoneItemUtil] AFTER recalculation:`, {
@@ -4928,13 +4952,30 @@ async function updateZoneItemUtil(db, appointmentId, zoneId, itemIndex, updates)
4928
4952
  newSubtotal: items[itemIndex].subtotal
4929
4953
  });
4930
4954
  const finalbilling = calculateFinalBilling(metadata.zonesData, 0.081);
4955
+ console.log(`[updateZoneItemUtil] Saving to Firestore:`, {
4956
+ appointmentId,
4957
+ zoneId,
4958
+ itemIndex,
4959
+ itemToSave: items[itemIndex],
4960
+ itemIonNumber: items[itemIndex].ionNumber,
4961
+ itemExpiryDate: items[itemIndex].expiryDate,
4962
+ zonesDataKeys: Object.keys(metadata.zonesData),
4963
+ zoneItemsCount: (_a = metadata.zonesData[zoneId]) == null ? void 0 : _a.length
4964
+ });
4931
4965
  const appointmentRef = (0, import_firestore8.doc)(db, APPOINTMENTS_COLLECTION, appointmentId);
4932
4966
  await (0, import_firestore7.updateDoc)(appointmentRef, {
4933
4967
  "metadata.zonesData": metadata.zonesData,
4934
4968
  "metadata.finalbilling": finalbilling,
4935
4969
  updatedAt: (0, import_firestore7.serverTimestamp)()
4936
4970
  });
4937
- return getAppointmentOrThrow(db, appointmentId);
4971
+ const savedAppointment = await getAppointmentOrThrow(db, appointmentId);
4972
+ const savedItem = (_d = (_c = (_b = savedAppointment.metadata) == null ? void 0 : _b.zonesData) == null ? void 0 : _c[zoneId]) == null ? void 0 : _d[itemIndex];
4973
+ console.log(`[updateZoneItemUtil] Verification after save:`, {
4974
+ savedItemIonNumber: savedItem == null ? void 0 : savedItem.ionNumber,
4975
+ savedItemExpiryDate: savedItem == null ? void 0 : savedItem.expiryDate,
4976
+ savedItemKeys: savedItem ? Object.keys(savedItem) : []
4977
+ });
4978
+ return savedAppointment;
4938
4979
  }
4939
4980
  async function overridePriceForZoneItemUtil(db, appointmentId, zoneId, itemIndex, newPrice) {
4940
4981
  return updateZoneItemUtil(db, appointmentId, zoneId, itemIndex, {
@@ -5064,7 +5105,9 @@ async function initializeFormsForExtendedProcedure(db, appointmentId, procedureI
5064
5105
  isRequired,
5065
5106
  sortingOrder: templateRef.sortingOrder,
5066
5107
  status: existingForm.status || "pending" /* PENDING */,
5067
- path: `${APPOINTMENTS_COLLECTION}/${appointmentId}/${formSubcollectionPath}/${existingForm.id}`
5108
+ path: `${APPOINTMENTS_COLLECTION}/${appointmentId}/${formSubcollectionPath}/${existingForm.id}`,
5109
+ procedureId
5110
+ // Track which procedure this form belongs to
5068
5111
  };
5069
5112
  initializedFormsInfo.push(linkedForm);
5070
5113
  if (!allLinkedFormIds.includes(existingForm.id)) {
@@ -5118,7 +5161,9 @@ async function initializeFormsForExtendedProcedure(db, appointmentId, procedureI
5118
5161
  isRequired,
5119
5162
  sortingOrder: templateRef.sortingOrder,
5120
5163
  status: "pending" /* PENDING */,
5121
- path: docRef.path
5164
+ path: docRef.path,
5165
+ procedureId
5166
+ // Track which procedure this form belongs to
5122
5167
  };
5123
5168
  initializedFormsInfo.push(linkedForm);
5124
5169
  const formType = isProcedureSpecific ? "procedure-specific" : "general/shared";
@@ -5310,6 +5355,8 @@ async function createExtendedProcedureInfo(db, procedureId) {
5310
5355
  return {
5311
5356
  procedureId,
5312
5357
  procedureName: data.name,
5358
+ procedureDescription: data.description || "",
5359
+ procedurePrice: data.price || 0,
5313
5360
  procedureFamily: data.family,
5314
5361
  // Use embedded family object
5315
5362
  procedureCategoryId: data.category.id,
@@ -5637,16 +5684,37 @@ async function getZonePhotoEntryUtil(db, appointmentId, zoneId, photoIndex) {
5637
5684
  return zoneArray[photoIndex];
5638
5685
  }
5639
5686
  async function updateZonePhotoVisibilityUtil(db, appointmentId, zoneId, photoIndex, showToPatient, doctorId) {
5687
+ const updates = { showToPatient };
5688
+ if (!showToPatient) {
5689
+ updates.beforeNoteVisibleToPatient = false;
5690
+ updates.afterNoteVisibleToPatient = false;
5691
+ }
5640
5692
  return updateZonePhotoEntryUtil(
5641
5693
  db,
5642
5694
  appointmentId,
5643
5695
  zoneId,
5644
5696
  photoIndex,
5645
- { showToPatient },
5697
+ updates,
5646
5698
  doctorId
5647
5699
  );
5648
5700
  }
5649
5701
  async function updateZonePhotoNoteVisibilityUtil(db, appointmentId, zoneId, photoIndex, noteType, visibleToPatient, doctorId) {
5702
+ var _a;
5703
+ const appointment = await getAppointmentOrThrow(db, appointmentId);
5704
+ const zonePhotos = (_a = appointment.metadata) == null ? void 0 : _a.zonePhotos;
5705
+ if (!zonePhotos || !zonePhotos[zoneId] || !Array.isArray(zonePhotos[zoneId])) {
5706
+ throw new Error(`No photos found for zone ${zoneId} in appointment ${appointmentId}`);
5707
+ }
5708
+ const zoneArray = zonePhotos[zoneId];
5709
+ if (photoIndex < 0 || photoIndex >= zoneArray.length) {
5710
+ throw new Error(`Invalid photo index ${photoIndex} for zone ${zoneId}. Must be between 0 and ${zoneArray.length - 1}`);
5711
+ }
5712
+ const photoEntry = zoneArray[photoIndex];
5713
+ if (visibleToPatient && !photoEntry.showToPatient) {
5714
+ throw new Error(
5715
+ 'Cannot make note visible to patient: The photo pair must be visible to the patient first. Please enable "Show to Patient" for the photo pair before making notes visible.'
5716
+ );
5717
+ }
5650
5718
  const updates = noteType === "before" ? { beforeNoteVisibleToPatient: visibleToPatient } : { afterNoteVisibleToPatient: visibleToPatient };
5651
5719
  return updateZonePhotoEntryUtil(db, appointmentId, zoneId, photoIndex, updates, doctorId);
5652
5720
  }
@@ -7290,6 +7358,8 @@ var AppointmentService = class extends BaseService {
7290
7358
  finalizationNotesInternal: currentMetadata.finalizationNotesInternal,
7291
7359
  finalizationNotes: currentMetadata.finalizationNotes
7292
7360
  });
7361
+ const normalizedSharedNotes = sharedNotes !== void 0 ? sharedNotes === "" || sharedNotes === null ? null : sharedNotes : currentMetadata.finalizationNotesShared;
7362
+ const normalizedInternalNotes = internalNotes !== void 0 ? internalNotes === "" || internalNotes === null ? null : internalNotes : currentMetadata.finalizationNotesInternal;
7293
7363
  const metadataUpdate = {
7294
7364
  selectedZones: currentMetadata.selectedZones,
7295
7365
  zonePhotos: currentMetadata.zonePhotos,
@@ -7298,21 +7368,38 @@ var AppointmentService = class extends BaseService {
7298
7368
  extendedProcedures: currentMetadata.extendedProcedures || [],
7299
7369
  recommendedProcedures: currentMetadata.recommendedProcedures || [],
7300
7370
  finalbilling: currentMetadata.finalbilling,
7301
- finalizationNotesShared: sharedNotes !== void 0 ? sharedNotes : currentMetadata.finalizationNotesShared,
7302
- finalizationNotesInternal: internalNotes !== void 0 ? internalNotes : currentMetadata.finalizationNotesInternal,
7371
+ finalizationNotesShared: normalizedSharedNotes,
7372
+ finalizationNotesInternal: normalizedInternalNotes,
7303
7373
  // Keep deprecated field for backward compatibility during migration
7304
- finalizationNotes: sharedNotes !== void 0 ? sharedNotes : currentMetadata.finalizationNotes || currentMetadata.finalizationNotesShared
7374
+ finalizationNotes: normalizedSharedNotes !== null && normalizedSharedNotes !== void 0 ? normalizedSharedNotes : currentMetadata.finalizationNotes || currentMetadata.finalizationNotesShared
7305
7375
  };
7306
7376
  console.log("\u{1F50D} [APPOINTMENT_SERVICE] Update data metadata:", {
7307
7377
  finalizationNotesShared: metadataUpdate.finalizationNotesShared,
7308
7378
  finalizationNotesInternal: metadataUpdate.finalizationNotesInternal,
7309
- finalizationNotes: metadataUpdate.finalizationNotes
7379
+ finalizationNotes: metadataUpdate.finalizationNotes,
7380
+ normalizedSharedNotes,
7381
+ normalizedInternalNotes
7310
7382
  });
7311
- const updateData = {
7312
- metadata: metadataUpdate,
7383
+ const appointmentRef = (0, import_firestore14.doc)(this.db, APPOINTMENTS_COLLECTION, appointmentId);
7384
+ const updateFields = {
7385
+ "metadata.finalizationNotesShared": normalizedSharedNotes,
7386
+ "metadata.finalizationNotesInternal": normalizedInternalNotes,
7387
+ "metadata.finalizationNotes": normalizedSharedNotes !== null && normalizedSharedNotes !== void 0 ? normalizedSharedNotes : currentMetadata.finalizationNotes || currentMetadata.finalizationNotesShared,
7313
7388
  updatedAt: (0, import_firestore14.serverTimestamp)()
7314
7389
  };
7315
- const result = await this.updateAppointment(appointmentId, updateData);
7390
+ console.log("\u{1F50D} [APPOINTMENT_SERVICE] Direct Firestore update with dot notation:", {
7391
+ appointmentId,
7392
+ updateFields: {
7393
+ "metadata.finalizationNotesShared": updateFields["metadata.finalizationNotesShared"],
7394
+ "metadata.finalizationNotesInternal": updateFields["metadata.finalizationNotesInternal"],
7395
+ "metadata.finalizationNotes": updateFields["metadata.finalizationNotes"]
7396
+ }
7397
+ });
7398
+ await (0, import_firestore14.updateDoc)(appointmentRef, updateFields);
7399
+ const result = await this.getAppointmentById(appointmentId);
7400
+ if (!result) {
7401
+ throw new Error(`Failed to retrieve updated appointment ${appointmentId}`);
7402
+ }
7316
7403
  console.log("\u{1F50D} [APPOINTMENT_SERVICE] After update, result metadata:", {
7317
7404
  finalizationNotesShared: (_a = result.metadata) == null ? void 0 : _a.finalizationNotesShared,
7318
7405
  finalizationNotesInternal: (_b = result.metadata) == null ? void 0 : _b.finalizationNotesInternal,