@blackcode_sa/metaestetics-api 1.12.39 โ†’ 1.12.41

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.
@@ -49,7 +49,12 @@ import { PatientService } from '../patient/patient.service';
49
49
  import { PractitionerService } from '../practitioner/practitioner.service';
50
50
  import { ClinicService } from '../clinic/clinic.service';
51
51
  import { FilledDocumentService } from '../documentation-templates/filled-document.service';
52
- import { MediaService, MediaAccessLevel, MediaMetadata, MediaResource } from '../media/media.service';
52
+ import {
53
+ MediaService,
54
+ MediaAccessLevel,
55
+ MediaMetadata,
56
+ MediaResource,
57
+ } from '../media/media.service';
53
58
 
54
59
  // Import utility functions
55
60
  import {
@@ -379,8 +384,72 @@ export class AppointmentService extends BaseService {
379
384
  try {
380
385
  console.log(`[APPOINTMENT_SERVICE] Updating appointment with ID: ${appointmentId}`);
381
386
 
387
+ // AUTO-MIGRATION: Convert old zonePhotos format to new array format BEFORE validation
388
+ if (data.metadata?.zonePhotos) {
389
+ const migratedZonePhotos: Record<string, BeforeAfterPerZone[]> = {};
390
+
391
+ for (const [key, value] of Object.entries(data.metadata.zonePhotos)) {
392
+ if (Array.isArray(value)) {
393
+ // Already in new format
394
+ migratedZonePhotos[key] = value as BeforeAfterPerZone[];
395
+ } else {
396
+ // Old format - convert to array
397
+ console.log(`[APPOINTMENT_SERVICE] Auto-migrating ${key} from object to array format`);
398
+ const oldData = value as any;
399
+ migratedZonePhotos[key] = [
400
+ {
401
+ before: oldData.before || null,
402
+ after: oldData.after || null,
403
+ beforeNote: null,
404
+ afterNote: null,
405
+ },
406
+ ];
407
+ }
408
+ }
409
+
410
+ // Replace with migrated data
411
+ data.metadata.zonePhotos = migratedZonePhotos;
412
+ }
413
+
414
+ // AUTO-CLEANUP: Remove invalid recommendedProcedures with empty notes BEFORE validation
415
+ console.log(
416
+ '[APPOINTMENT_SERVICE] ๐Ÿ” BEFORE CLEANUP - recommendedProcedures:',
417
+ JSON.stringify(data.metadata?.recommendedProcedures, null, 2),
418
+ );
419
+
420
+ if (
421
+ data.metadata?.recommendedProcedures &&
422
+ Array.isArray(data.metadata.recommendedProcedures)
423
+ ) {
424
+ const validRecommendations = data.metadata.recommendedProcedures.filter((rec: any) => {
425
+ const isValid = rec.note && typeof rec.note === 'string' && rec.note.trim().length > 0;
426
+ if (!isValid) {
427
+ console.log('[APPOINTMENT_SERVICE] โŒ INVALID recommendation found:', rec);
428
+ }
429
+ return isValid;
430
+ });
431
+
432
+ if (validRecommendations.length !== data.metadata.recommendedProcedures.length) {
433
+ console.log(
434
+ `[APPOINTMENT_SERVICE] ๐Ÿงน Removing ${
435
+ data.metadata.recommendedProcedures.length - validRecommendations.length
436
+ } invalid recommended procedures with empty notes`,
437
+ );
438
+ data.metadata.recommendedProcedures = validRecommendations;
439
+ } else {
440
+ console.log('[APPOINTMENT_SERVICE] โœ… All recommendedProcedures are valid');
441
+ }
442
+ }
443
+
444
+ console.log(
445
+ '[APPOINTMENT_SERVICE] ๐Ÿ” AFTER CLEANUP - recommendedProcedures:',
446
+ JSON.stringify(data.metadata?.recommendedProcedures, null, 2),
447
+ );
448
+
382
449
  // Validate input data
450
+ console.log('[APPOINTMENT_SERVICE] ๐Ÿ” Starting Zod validation...');
383
451
  const validatedData = await updateAppointmentSchema.parseAsync(data);
452
+ console.log('[APPOINTMENT_SERVICE] โœ… Zod validation passed!');
384
453
 
385
454
  // Update the appointment using the utility function
386
455
  const updatedAppointment = await updateAppointmentUtil(this.db, appointmentId, validatedData);
@@ -1294,8 +1363,29 @@ export class AppointmentService extends BaseService {
1294
1363
  };
1295
1364
 
1296
1365
  // Initialize zonePhotos if it doesn't exist (array model per zone)
1297
- const currentZonePhotos: Record<string, BeforeAfterPerZone[]> =
1298
- (currentMetadata.zonePhotos as Record<string, BeforeAfterPerZone[]>) || {};
1366
+ let currentZonePhotos: Record<string, BeforeAfterPerZone[]> = {};
1367
+
1368
+ // AUTO-MIGRATION: Convert old object format to new array format
1369
+ if (currentMetadata.zonePhotos) {
1370
+ for (const [key, value] of Object.entries(currentMetadata.zonePhotos)) {
1371
+ if (Array.isArray(value)) {
1372
+ // Already in new format
1373
+ currentZonePhotos[key] = value as BeforeAfterPerZone[];
1374
+ } else {
1375
+ // Old format - convert to array
1376
+ console.log(`[APPOINTMENT_SERVICE] Auto-migrating ${key} from object to array format`);
1377
+ const oldData = value as any;
1378
+ currentZonePhotos[key] = [
1379
+ {
1380
+ before: oldData.before || null,
1381
+ after: oldData.after || null,
1382
+ beforeNote: null,
1383
+ afterNote: null,
1384
+ },
1385
+ ];
1386
+ }
1387
+ }
1388
+ }
1299
1389
 
1300
1390
  // Initialize the zone array if it doesn't exist
1301
1391
  if (!currentZonePhotos[zoneId]) {
@@ -1306,8 +1396,8 @@ export class AppointmentService extends BaseService {
1306
1396
  const newEntry: BeforeAfterPerZone = {
1307
1397
  before: photoType === 'before' ? mediaMetadata.url : null,
1308
1398
  after: photoType === 'after' ? mediaMetadata.url : null,
1309
- beforeNote: photoType === 'before' ? (notes || null) : null,
1310
- afterNote: photoType === 'after' ? (notes || null) : null,
1399
+ beforeNote: photoType === 'before' ? notes || null : null,
1400
+ afterNote: photoType === 'after' ? notes || null : null,
1311
1401
  };
1312
1402
 
1313
1403
  // Append to the zone's photo list
@@ -1778,13 +1868,19 @@ export class AppointmentService extends BaseService {
1778
1868
  appointmentId: string,
1779
1869
  procedureId: string,
1780
1870
  note: string,
1781
- timeframe: { value: number; unit: 'day' | 'week' | 'month' | 'year' }
1871
+ timeframe: { value: number; unit: 'day' | 'week' | 'month' | 'year' },
1782
1872
  ): Promise<Appointment> {
1783
1873
  try {
1784
1874
  console.log(
1785
1875
  `[APPOINTMENT_SERVICE] Adding recommended procedure ${procedureId} to appointment ${appointmentId}`,
1786
1876
  );
1787
- return await addRecommendedProcedureUtil(this.db, appointmentId, procedureId, note, timeframe);
1877
+ return await addRecommendedProcedureUtil(
1878
+ this.db,
1879
+ appointmentId,
1880
+ procedureId,
1881
+ note,
1882
+ timeframe,
1883
+ );
1788
1884
  } catch (error) {
1789
1885
  console.error(`[APPOINTMENT_SERVICE] Error adding recommended procedure:`, error);
1790
1886
  throw error;
@@ -1798,7 +1894,10 @@ export class AppointmentService extends BaseService {
1798
1894
  * @param recommendationIndex Index of the recommendation to remove
1799
1895
  * @returns The updated appointment
1800
1896
  */
1801
- async removeRecommendedProcedure(appointmentId: string, recommendationIndex: number): Promise<Appointment> {
1897
+ async removeRecommendedProcedure(
1898
+ appointmentId: string,
1899
+ recommendationIndex: number,
1900
+ ): Promise<Appointment> {
1802
1901
  try {
1803
1902
  console.log(
1804
1903
  `[APPOINTMENT_SERVICE] Removing recommended procedure at index ${recommendationIndex} from appointment ${appointmentId}`,
@@ -1824,13 +1923,18 @@ export class AppointmentService extends BaseService {
1824
1923
  updates: {
1825
1924
  note?: string;
1826
1925
  timeframe?: { value: number; unit: 'day' | 'week' | 'month' | 'year' };
1827
- }
1926
+ },
1828
1927
  ): Promise<Appointment> {
1829
1928
  try {
1830
1929
  console.log(
1831
1930
  `[APPOINTMENT_SERVICE] Updating recommended procedure at index ${recommendationIndex} in appointment ${appointmentId}`,
1832
1931
  );
1833
- return await updateRecommendedProcedureUtil(this.db, appointmentId, recommendationIndex, updates);
1932
+ return await updateRecommendedProcedureUtil(
1933
+ this.db,
1934
+ appointmentId,
1935
+ recommendationIndex,
1936
+ updates,
1937
+ );
1834
1938
  } catch (error) {
1835
1939
  console.error(`[APPOINTMENT_SERVICE] Error updating recommended procedure:`, error);
1836
1940
  throw error;
@@ -1869,7 +1973,7 @@ export class AppointmentService extends BaseService {
1869
1973
  appointmentId: string,
1870
1974
  zoneId: string,
1871
1975
  photoIndex: number,
1872
- updates: Partial<BeforeAfterPerZone>
1976
+ updates: Partial<BeforeAfterPerZone>,
1873
1977
  ): Promise<Appointment> {
1874
1978
  try {
1875
1979
  console.log(
@@ -1897,7 +2001,7 @@ export class AppointmentService extends BaseService {
1897
2001
  zoneId: string,
1898
2002
  photoIndex: number,
1899
2003
  afterPhotoUrl: MediaResource,
1900
- afterNote?: string
2004
+ afterNote?: string,
1901
2005
  ): Promise<Appointment> {
1902
2006
  try {
1903
2007
  console.log(
@@ -1909,7 +2013,7 @@ export class AppointmentService extends BaseService {
1909
2013
  zoneId,
1910
2014
  photoIndex,
1911
2015
  afterPhotoUrl,
1912
- afterNote
2016
+ afterNote,
1913
2017
  );
1914
2018
  } catch (error) {
1915
2019
  console.error(`[APPOINTMENT_SERVICE] Error adding after photo to entry:`, error);
@@ -1932,7 +2036,7 @@ export class AppointmentService extends BaseService {
1932
2036
  zoneId: string,
1933
2037
  photoIndex: number,
1934
2038
  beforeNote?: string,
1935
- afterNote?: string
2039
+ afterNote?: string,
1936
2040
  ): Promise<Appointment> {
1937
2041
  try {
1938
2042
  console.log(
@@ -1944,7 +2048,7 @@ export class AppointmentService extends BaseService {
1944
2048
  zoneId,
1945
2049
  photoIndex,
1946
2050
  beforeNote,
1947
- afterNote
2051
+ afterNote,
1948
2052
  );
1949
2053
  } catch (error) {
1950
2054
  console.error(`[APPOINTMENT_SERVICE] Error updating zone photo notes:`, error);
@@ -1963,7 +2067,7 @@ export class AppointmentService extends BaseService {
1963
2067
  async getZonePhotoEntry(
1964
2068
  appointmentId: string,
1965
2069
  zoneId: string,
1966
- photoIndex: number
2070
+ photoIndex: number,
1967
2071
  ): Promise<BeforeAfterPerZone> {
1968
2072
  try {
1969
2073
  console.log(