@blackcode_sa/metaestetics-api 1.14.59 → 1.14.61

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.
@@ -4723,6 +4723,12 @@ declare class NotificationsAdmin {
4723
4723
  * Kreira novu notifikaciju
4724
4724
  */
4725
4725
  createNotification(notification: Omit<Notification, "id">): Promise<string>;
4726
+ /**
4727
+ * Creates a notification and immediately attempts to send it.
4728
+ * If immediate send fails, the notification remains PENDING for cron pickup.
4729
+ * Returns the notification ID regardless of send success.
4730
+ */
4731
+ createAndSendNotificationImmediately(notification: Omit<Notification, "id">): Promise<string>;
4726
4732
  /**
4727
4733
  * Priprema Expo poruku za slanje
4728
4734
  */
@@ -4723,6 +4723,12 @@ declare class NotificationsAdmin {
4723
4723
  * Kreira novu notifikaciju
4724
4724
  */
4725
4725
  createNotification(notification: Omit<Notification, "id">): Promise<string>;
4726
+ /**
4727
+ * Creates a notification and immediately attempts to send it.
4728
+ * If immediate send fails, the notification remains PENDING for cron pickup.
4729
+ * Returns the notification ID regardless of send success.
4730
+ */
4731
+ createAndSendNotificationImmediately(notification: Omit<Notification, "id">): Promise<string>;
4726
4732
  /**
4727
4733
  * Priprema Expo poruku za slanje
4728
4734
  */
@@ -717,6 +717,37 @@ var NotificationsAdmin = class {
717
717
  });
718
718
  return docRef.id;
719
719
  }
720
+ /**
721
+ * Creates a notification and immediately attempts to send it.
722
+ * If immediate send fails, the notification remains PENDING for cron pickup.
723
+ * Returns the notification ID regardless of send success.
724
+ */
725
+ async createAndSendNotificationImmediately(notification) {
726
+ const notificationId = await this.createNotification(notification);
727
+ try {
728
+ const fullNotification = {
729
+ ...notification,
730
+ id: notificationId,
731
+ status: "pending" /* PENDING */
732
+ };
733
+ const sent = await this.sendPushNotification(fullNotification);
734
+ if (sent) {
735
+ Logger.info(
736
+ `[NotificationsAdmin] Notification ${notificationId} sent immediately`
737
+ );
738
+ } else {
739
+ Logger.info(
740
+ `[NotificationsAdmin] Notification ${notificationId} immediate send failed, will be retried by cron`
741
+ );
742
+ }
743
+ } catch (error) {
744
+ Logger.error(
745
+ `[NotificationsAdmin] Error sending notification ${notificationId} immediately, will be retried by cron:`,
746
+ error
747
+ );
748
+ }
749
+ return notificationId;
750
+ }
720
751
  /**
721
752
  * Priprema Expo poruku za slanje
722
753
  */
@@ -740,7 +771,15 @@ var NotificationsAdmin = class {
740
771
  data: {
741
772
  notificationId: notification.id,
742
773
  notificationType: notification.notificationType,
743
- userId: notification.userId
774
+ userId: notification.userId,
775
+ // Deep linking data
776
+ type: notification.appointmentId ? "appointment" : "system",
777
+ appointmentId: notification.appointmentId,
778
+ // Explicit deep link for navigation
779
+ deepLink: notification.appointmentId ? {
780
+ screen: "AppointmentDetail",
781
+ params: { appointmentId: notification.appointmentId }
782
+ } : void 0
744
783
  }
745
784
  }));
746
785
  }
@@ -983,7 +1022,7 @@ var NotificationsAdmin = class {
983
1022
  appointmentId: appointment.id
984
1023
  };
985
1024
  try {
986
- const notificationId = await this.createNotification(
1025
+ const notificationId = await this.createAndSendNotificationImmediately(
987
1026
  notificationData
988
1027
  );
989
1028
  console.log(
@@ -1034,7 +1073,7 @@ var NotificationsAdmin = class {
1034
1073
  appointmentId: appointment.id
1035
1074
  };
1036
1075
  try {
1037
- const notificationId = await this.createNotification(
1076
+ const notificationId = await this.createAndSendNotificationImmediately(
1038
1077
  notificationData
1039
1078
  );
1040
1079
  console.log(
@@ -1070,7 +1109,7 @@ var NotificationsAdmin = class {
1070
1109
  appointmentId: appointment.id
1071
1110
  };
1072
1111
  try {
1073
- const notificationId = await this.createNotification(
1112
+ const notificationId = await this.createAndSendNotificationImmediately(
1074
1113
  notificationData
1075
1114
  );
1076
1115
  console.log(
@@ -1107,7 +1146,7 @@ var NotificationsAdmin = class {
1107
1146
  appointmentId: appointment.id
1108
1147
  };
1109
1148
  try {
1110
- const notificationId = await this.createNotification(
1149
+ const notificationId = await this.createAndSendNotificationImmediately(
1111
1150
  notificationData
1112
1151
  );
1113
1152
  console.log(
@@ -1143,7 +1182,7 @@ var NotificationsAdmin = class {
1143
1182
  appointmentId: appointment.id
1144
1183
  };
1145
1184
  try {
1146
- const notificationId = await this.createNotification(
1185
+ const notificationId = await this.createAndSendNotificationImmediately(
1147
1186
  notificationData
1148
1187
  );
1149
1188
  console.log(
@@ -1186,7 +1225,7 @@ var NotificationsAdmin = class {
1186
1225
  appointmentId: appointment.id
1187
1226
  };
1188
1227
  try {
1189
- const notificationId = await this.createNotification(
1228
+ const notificationId = await this.createAndSendNotificationImmediately(
1190
1229
  notificationData
1191
1230
  );
1192
1231
  console.log(
@@ -1230,7 +1269,7 @@ var NotificationsAdmin = class {
1230
1269
  appointmentId: appointment.id
1231
1270
  };
1232
1271
  try {
1233
- const notificationId = await this.createNotification(
1272
+ const notificationId = await this.createAndSendNotificationImmediately(
1234
1273
  notificationData
1235
1274
  );
1236
1275
  console.log(
@@ -3735,12 +3774,11 @@ var AppointmentAggregationService = class {
3735
3774
  const patientCancellationData = {
3736
3775
  appointment: after,
3737
3776
  recipientProfile: after.patientInfo,
3738
- recipientRole: "patient"
3739
- // cancellationReason: after.cancellationReason, // TODO: Add if cancellationReason is available on 'after' Appointment
3777
+ recipientRole: "patient",
3778
+ cancellationReason: after.cancellationReason
3740
3779
  };
3741
3780
  await this.appointmentMailingService.sendAppointmentCancelledEmail(
3742
3781
  patientCancellationData
3743
- // TODO: Properly import types
3744
3782
  );
3745
3783
  }
3746
3784
  if ((_c = practitionerProfile == null ? void 0 : practitionerProfile.basicInfo) == null ? void 0 : _c.email) {
@@ -3750,12 +3788,22 @@ var AppointmentAggregationService = class {
3750
3788
  const practitionerCancellationData = {
3751
3789
  appointment: after,
3752
3790
  recipientProfile: after.practitionerInfo,
3753
- recipientRole: "practitioner"
3754
- // cancellationReason: after.cancellationReason, // TODO: Add if cancellationReason is available on 'after' Appointment
3791
+ recipientRole: "practitioner",
3792
+ cancellationReason: after.cancellationReason
3755
3793
  };
3756
3794
  await this.appointmentMailingService.sendAppointmentCancelledEmail(
3757
3795
  practitionerCancellationData
3758
- // TODO: Properly import types
3796
+ );
3797
+ }
3798
+ if ((patientProfile == null ? void 0 : patientProfile.expoTokens) && patientProfile.expoTokens.length > 0) {
3799
+ Logger.info(
3800
+ `[AggService] Sending cancellation push notification to patient ${after.patientId}`
3801
+ );
3802
+ await this.notificationsAdmin.sendAppointmentCancelledPush(
3803
+ after,
3804
+ after.patientId,
3805
+ patientProfile.expoTokens,
3806
+ "patient" /* PATIENT */
3759
3807
  );
3760
3808
  }
3761
3809
  } else if (after.status === "completed" /* COMPLETED */) {
@@ -641,6 +641,37 @@ var NotificationsAdmin = class {
641
641
  });
642
642
  return docRef.id;
643
643
  }
644
+ /**
645
+ * Creates a notification and immediately attempts to send it.
646
+ * If immediate send fails, the notification remains PENDING for cron pickup.
647
+ * Returns the notification ID regardless of send success.
648
+ */
649
+ async createAndSendNotificationImmediately(notification) {
650
+ const notificationId = await this.createNotification(notification);
651
+ try {
652
+ const fullNotification = {
653
+ ...notification,
654
+ id: notificationId,
655
+ status: "pending" /* PENDING */
656
+ };
657
+ const sent = await this.sendPushNotification(fullNotification);
658
+ if (sent) {
659
+ Logger.info(
660
+ `[NotificationsAdmin] Notification ${notificationId} sent immediately`
661
+ );
662
+ } else {
663
+ Logger.info(
664
+ `[NotificationsAdmin] Notification ${notificationId} immediate send failed, will be retried by cron`
665
+ );
666
+ }
667
+ } catch (error) {
668
+ Logger.error(
669
+ `[NotificationsAdmin] Error sending notification ${notificationId} immediately, will be retried by cron:`,
670
+ error
671
+ );
672
+ }
673
+ return notificationId;
674
+ }
644
675
  /**
645
676
  * Priprema Expo poruku za slanje
646
677
  */
@@ -664,7 +695,15 @@ var NotificationsAdmin = class {
664
695
  data: {
665
696
  notificationId: notification.id,
666
697
  notificationType: notification.notificationType,
667
- userId: notification.userId
698
+ userId: notification.userId,
699
+ // Deep linking data
700
+ type: notification.appointmentId ? "appointment" : "system",
701
+ appointmentId: notification.appointmentId,
702
+ // Explicit deep link for navigation
703
+ deepLink: notification.appointmentId ? {
704
+ screen: "AppointmentDetail",
705
+ params: { appointmentId: notification.appointmentId }
706
+ } : void 0
668
707
  }
669
708
  }));
670
709
  }
@@ -907,7 +946,7 @@ var NotificationsAdmin = class {
907
946
  appointmentId: appointment.id
908
947
  };
909
948
  try {
910
- const notificationId = await this.createNotification(
949
+ const notificationId = await this.createAndSendNotificationImmediately(
911
950
  notificationData
912
951
  );
913
952
  console.log(
@@ -958,7 +997,7 @@ var NotificationsAdmin = class {
958
997
  appointmentId: appointment.id
959
998
  };
960
999
  try {
961
- const notificationId = await this.createNotification(
1000
+ const notificationId = await this.createAndSendNotificationImmediately(
962
1001
  notificationData
963
1002
  );
964
1003
  console.log(
@@ -994,7 +1033,7 @@ var NotificationsAdmin = class {
994
1033
  appointmentId: appointment.id
995
1034
  };
996
1035
  try {
997
- const notificationId = await this.createNotification(
1036
+ const notificationId = await this.createAndSendNotificationImmediately(
998
1037
  notificationData
999
1038
  );
1000
1039
  console.log(
@@ -1031,7 +1070,7 @@ var NotificationsAdmin = class {
1031
1070
  appointmentId: appointment.id
1032
1071
  };
1033
1072
  try {
1034
- const notificationId = await this.createNotification(
1073
+ const notificationId = await this.createAndSendNotificationImmediately(
1035
1074
  notificationData
1036
1075
  );
1037
1076
  console.log(
@@ -1067,7 +1106,7 @@ var NotificationsAdmin = class {
1067
1106
  appointmentId: appointment.id
1068
1107
  };
1069
1108
  try {
1070
- const notificationId = await this.createNotification(
1109
+ const notificationId = await this.createAndSendNotificationImmediately(
1071
1110
  notificationData
1072
1111
  );
1073
1112
  console.log(
@@ -1110,7 +1149,7 @@ var NotificationsAdmin = class {
1110
1149
  appointmentId: appointment.id
1111
1150
  };
1112
1151
  try {
1113
- const notificationId = await this.createNotification(
1152
+ const notificationId = await this.createAndSendNotificationImmediately(
1114
1153
  notificationData
1115
1154
  );
1116
1155
  console.log(
@@ -1154,7 +1193,7 @@ var NotificationsAdmin = class {
1154
1193
  appointmentId: appointment.id
1155
1194
  };
1156
1195
  try {
1157
- const notificationId = await this.createNotification(
1196
+ const notificationId = await this.createAndSendNotificationImmediately(
1158
1197
  notificationData
1159
1198
  );
1160
1199
  console.log(
@@ -3659,12 +3698,11 @@ var AppointmentAggregationService = class {
3659
3698
  const patientCancellationData = {
3660
3699
  appointment: after,
3661
3700
  recipientProfile: after.patientInfo,
3662
- recipientRole: "patient"
3663
- // cancellationReason: after.cancellationReason, // TODO: Add if cancellationReason is available on 'after' Appointment
3701
+ recipientRole: "patient",
3702
+ cancellationReason: after.cancellationReason
3664
3703
  };
3665
3704
  await this.appointmentMailingService.sendAppointmentCancelledEmail(
3666
3705
  patientCancellationData
3667
- // TODO: Properly import types
3668
3706
  );
3669
3707
  }
3670
3708
  if ((_c = practitionerProfile == null ? void 0 : practitionerProfile.basicInfo) == null ? void 0 : _c.email) {
@@ -3674,12 +3712,22 @@ var AppointmentAggregationService = class {
3674
3712
  const practitionerCancellationData = {
3675
3713
  appointment: after,
3676
3714
  recipientProfile: after.practitionerInfo,
3677
- recipientRole: "practitioner"
3678
- // cancellationReason: after.cancellationReason, // TODO: Add if cancellationReason is available on 'after' Appointment
3715
+ recipientRole: "practitioner",
3716
+ cancellationReason: after.cancellationReason
3679
3717
  };
3680
3718
  await this.appointmentMailingService.sendAppointmentCancelledEmail(
3681
3719
  practitionerCancellationData
3682
- // TODO: Properly import types
3720
+ );
3721
+ }
3722
+ if ((patientProfile == null ? void 0 : patientProfile.expoTokens) && patientProfile.expoTokens.length > 0) {
3723
+ Logger.info(
3724
+ `[AggService] Sending cancellation push notification to patient ${after.patientId}`
3725
+ );
3726
+ await this.notificationsAdmin.sendAppointmentCancelledPush(
3727
+ after,
3728
+ after.patientId,
3729
+ patientProfile.expoTokens,
3730
+ "patient" /* PATIENT */
3683
3731
  );
3684
3732
  }
3685
3733
  } else if (after.status === "completed" /* COMPLETED */) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@blackcode_sa/metaestetics-api",
3
3
  "private": false,
4
- "version": "1.14.59",
4
+ "version": "1.14.61",
5
5
  "description": "Firebase authentication service with anonymous upgrade support",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.mjs",
@@ -408,10 +408,10 @@ export class AppointmentAggregationService {
408
408
  appointment: after,
409
409
  recipientProfile: after.patientInfo,
410
410
  recipientRole: 'patient' as const,
411
- // cancellationReason: after.cancellationReason, // TODO: Add if cancellationReason is available on 'after' Appointment
411
+ cancellationReason: after.cancellationReason,
412
412
  };
413
413
  await this.appointmentMailingService.sendAppointmentCancelledEmail(
414
- patientCancellationData as any, // TODO: Properly import types
414
+ patientCancellationData as any,
415
415
  );
416
416
  }
417
417
 
@@ -424,15 +424,25 @@ export class AppointmentAggregationService {
424
424
  appointment: after,
425
425
  recipientProfile: after.practitionerInfo,
426
426
  recipientRole: 'practitioner' as const,
427
- // cancellationReason: after.cancellationReason, // TODO: Add if cancellationReason is available on 'after' Appointment
427
+ cancellationReason: after.cancellationReason,
428
428
  };
429
429
  await this.appointmentMailingService.sendAppointmentCancelledEmail(
430
- practitionerCancellationData as any, // TODO: Properly import types
430
+ practitionerCancellationData as any,
431
431
  );
432
432
  }
433
433
 
434
- // TODO: Send cancellation push notifications (patient, practitioner) via notificationsAdmin
435
- // TODO: Update/cancel calendar event via calendarAdminService.updateAppointmentCalendarEventStatus(after, CalendarEventStatus.CANCELED)
434
+ // Send cancellation push notification to Patient
435
+ if (patientProfile?.expoTokens && patientProfile.expoTokens.length > 0) {
436
+ Logger.info(
437
+ `[AggService] Sending cancellation push notification to patient ${after.patientId}`,
438
+ );
439
+ await this.notificationsAdmin.sendAppointmentCancelledPush(
440
+ after,
441
+ after.patientId,
442
+ patientProfile.expoTokens,
443
+ UserRole.PATIENT,
444
+ );
445
+ }
436
446
  }
437
447
  // --- Any -> COMPLETED ---
438
448
  else if (after.status === AppointmentStatus.COMPLETED) {
@@ -43,6 +43,47 @@ export class NotificationsAdmin {
43
43
  return docRef.id;
44
44
  }
45
45
 
46
+ /**
47
+ * Creates a notification and immediately attempts to send it.
48
+ * If immediate send fails, the notification remains PENDING for cron pickup.
49
+ * Returns the notification ID regardless of send success.
50
+ */
51
+ async createAndSendNotificationImmediately(
52
+ notification: Omit<Notification, "id">
53
+ ): Promise<string> {
54
+ // Create the notification first
55
+ const notificationId = await this.createNotification(notification);
56
+
57
+ // Immediately try to send it
58
+ try {
59
+ const fullNotification: Notification = {
60
+ ...notification,
61
+ id: notificationId,
62
+ status: NotificationStatus.PENDING,
63
+ } as Notification;
64
+
65
+ const sent = await this.sendPushNotification(fullNotification);
66
+
67
+ if (sent) {
68
+ Logger.info(
69
+ `[NotificationsAdmin] Notification ${notificationId} sent immediately`
70
+ );
71
+ } else {
72
+ Logger.info(
73
+ `[NotificationsAdmin] Notification ${notificationId} immediate send failed, will be retried by cron`
74
+ );
75
+ }
76
+ } catch (error) {
77
+ // Don't throw - notification is created, cron will pick it up
78
+ Logger.error(
79
+ `[NotificationsAdmin] Error sending notification ${notificationId} immediately, will be retried by cron:`,
80
+ error
81
+ );
82
+ }
83
+
84
+ return notificationId;
85
+ }
86
+
46
87
  /**
47
88
  * Priprema Expo poruku za slanje
48
89
  */
@@ -70,6 +111,16 @@ export class NotificationsAdmin {
70
111
  notificationId: notification.id,
71
112
  notificationType: notification.notificationType,
72
113
  userId: notification.userId,
114
+ // Deep linking data
115
+ type: notification.appointmentId ? 'appointment' : 'system',
116
+ appointmentId: notification.appointmentId,
117
+ // Explicit deep link for navigation
118
+ deepLink: notification.appointmentId
119
+ ? {
120
+ screen: 'AppointmentDetail',
121
+ params: { appointmentId: notification.appointmentId },
122
+ }
123
+ : undefined,
73
124
  },
74
125
  }));
75
126
  }
@@ -406,7 +457,7 @@ export class NotificationsAdmin {
406
457
  };
407
458
 
408
459
  try {
409
- const notificationId = await this.createNotification(
460
+ const notificationId = await this.createAndSendNotificationImmediately(
410
461
  notificationData as Notification
411
462
  );
412
463
  console.log(
@@ -479,7 +530,7 @@ export class NotificationsAdmin {
479
530
  };
480
531
 
481
532
  try {
482
- const notificationId = await this.createNotification(
533
+ const notificationId = await this.createAndSendNotificationImmediately(
483
534
  notificationData as Notification
484
535
  );
485
536
  console.log(
@@ -527,7 +578,7 @@ export class NotificationsAdmin {
527
578
  };
528
579
 
529
580
  try {
530
- const notificationId = await this.createNotification(
581
+ const notificationId = await this.createAndSendNotificationImmediately(
531
582
  notificationData as Notification
532
583
  );
533
584
  console.log(
@@ -583,7 +634,7 @@ export class NotificationsAdmin {
583
634
  };
584
635
 
585
636
  try {
586
- const notificationId = await this.createNotification(
637
+ const notificationId = await this.createAndSendNotificationImmediately(
587
638
  notificationData as Notification
588
639
  );
589
640
  console.log(
@@ -631,7 +682,7 @@ export class NotificationsAdmin {
631
682
  };
632
683
 
633
684
  try {
634
- const notificationId = await this.createNotification(
685
+ const notificationId = await this.createAndSendNotificationImmediately(
635
686
  notificationData as Notification
636
687
  );
637
688
  console.log(
@@ -692,7 +743,7 @@ export class NotificationsAdmin {
692
743
  };
693
744
 
694
745
  try {
695
- const notificationId = await this.createNotification(
746
+ const notificationId = await this.createAndSendNotificationImmediately(
696
747
  notificationData as Notification
697
748
  );
698
749
  console.log(
@@ -749,7 +800,7 @@ export class NotificationsAdmin {
749
800
  };
750
801
 
751
802
  try {
752
- const notificationId = await this.createNotification(
803
+ const notificationId = await this.createAndSendNotificationImmediately(
753
804
  notificationData as Notification
754
805
  );
755
806
  console.log(