@@ -38,6 +38,10 @@ class NotificationService {
3838 // }
3939 // }
4040 mapStringToTypeNotification ( type ) {
41+ const normalized = type . trim ( ) . toUpperCase ( ) ;
42+ if ( Object . values ( Notification_1 . TypeNotification ) . includes ( normalized ) ) {
43+ return normalized ;
44+ }
4145 switch ( type ) {
4246 case "transfer" :
4347 return Notification_1 . TypeNotification . CONFIRMATION_TRANSFERT ;
@@ -114,6 +118,58 @@ class NotificationService {
114118 email : notifEmail ,
115119 } ;
116120 }
121+ async sendSmsPriorityToContact ( contact , content , type , role , extraContext ) {
122+ const context = { ...( extraContext || { } ) , role } ;
123+ const notifSms = this . notifRepo . create ( {
124+ utilisateurId : contact . phone ,
125+ typeNotification : type ,
126+ canal : Notification_1 . CanalNotification . SMS ,
127+ context,
128+ message : content ,
129+ destinationPhone : contact . phone ,
130+ statut : Notification_1 . StatutNotification . EN_COURS ,
131+ } ) ;
132+ await this . notifRepo . save ( notifSms ) ;
133+ try {
134+ await client . messages . create ( {
135+ body : content ,
136+ from : process . env . TWILIO_PHONE_NUMBER ,
137+ to : contact . phone ,
138+ } ) ;
139+ notifSms . statut = Notification_1 . StatutNotification . ENVOYEE ;
140+ }
141+ catch ( error ) {
142+ notifSms . statut = Notification_1 . StatutNotification . ECHEC ;
143+ console . error ( "Erreur d'envoi SMS :" , error ) ;
144+ }
145+ await this . notifRepo . save ( notifSms ) ;
146+ let notifEmail ;
147+ if ( contact . email ) {
148+ notifEmail = this . notifRepo . create ( {
149+ utilisateurId : contact . email ,
150+ typeNotification : type ,
151+ canal : Notification_1 . CanalNotification . EMAIL ,
152+ context,
153+ message : content ,
154+ destinationEmail : contact . email ,
155+ statut : Notification_1 . StatutNotification . EN_COURS ,
156+ } ) ;
157+ await this . notifRepo . save ( notifEmail ) ;
158+ try {
159+ await ( 0 , mailService_1 . sendEmail ) ( contact . email , "Notification" , content ) ;
160+ notifEmail . statut = Notification_1 . StatutNotification . ENVOYEE ;
161+ }
162+ catch ( error ) {
163+ notifEmail . statut = Notification_1 . StatutNotification . ECHEC ;
164+ console . error ( "Erreur d'envoi email :" , error ) ;
165+ }
166+ await this . notifRepo . save ( notifEmail ) ;
167+ }
168+ return {
169+ sms : notifSms ,
170+ ...( notifEmail ? { email : notifEmail } : { } ) ,
171+ } ;
172+ }
117173 /**
118174 * Endpoint HTTP (Postman) :
119175 * - dépend UNIQUEMENT des coordonnées fournies dans le JSON
@@ -131,6 +187,15 @@ class NotificationService {
131187 receiver : receiverResult ,
132188 } ;
133189 }
190+ if ( payload . type === "alert_securite" ||
191+ payload . type === "ALERT_SECURITE" ) {
192+ const alertPayload = payload ;
193+ const type = this . mapStringToTypeNotification ( alertPayload . type ) ;
194+ const userResult = await this . sendSmsPriorityToContact ( alertPayload . user , alertPayload . content , type , "USER" ) ;
195+ return {
196+ user : userResult ,
197+ } ;
198+ }
134199 const simplePayload = payload ;
135200 const type = this . mapStringToTypeNotification ( simplePayload . type ) ;
136201 const userResult = await this . sendMultiChannelToContact ( simplePayload . user , simplePayload . content , type , "USER" ) ;
@@ -158,6 +223,63 @@ class NotificationService {
158223 if ( ! destinationEmail && ! destinationPhone ) {
159224 throw new Error ( `Aucun contact (email ou téléphone) disponible pour l'utilisateur ${ data . utilisateurId } ` ) ;
160225 }
226+ // Priorité SMS pour les alertes sécurité: SMS d'abord si numéro disponible,
227+ // puis email en second canal si disponible.
228+ if ( data . typeNotification === Notification_1 . TypeNotification . ALERT_SECURITE ) {
229+ const context = data . context ;
230+ let smsNotif ;
231+ let emailNotif ;
232+ if ( destinationPhone ) {
233+ smsNotif = this . notifRepo . create ( {
234+ utilisateurId : data . utilisateurId ,
235+ typeNotification : data . typeNotification ,
236+ canal : Notification_1 . CanalNotification . SMS ,
237+ context,
238+ message,
239+ destinationPhone,
240+ statut : Notification_1 . StatutNotification . EN_COURS ,
241+ } ) ;
242+ await this . notifRepo . save ( smsNotif ) ;
243+ try {
244+ await client . messages . create ( {
245+ body : message ,
246+ from : process . env . TWILIO_PHONE_NUMBER ,
247+ to : destinationPhone ,
248+ } ) ;
249+ smsNotif . statut = Notification_1 . StatutNotification . ENVOYEE ;
250+ }
251+ catch ( error ) {
252+ smsNotif . statut = Notification_1 . StatutNotification . ECHEC ;
253+ console . error ( "Erreur d'envoi SMS :" , error ) ;
254+ }
255+ await this . notifRepo . save ( smsNotif ) ;
256+ }
257+ if ( destinationEmail ) {
258+ emailNotif = this . notifRepo . create ( {
259+ utilisateurId : data . utilisateurId ,
260+ typeNotification : data . typeNotification ,
261+ canal : Notification_1 . CanalNotification . EMAIL ,
262+ context,
263+ message,
264+ destinationEmail,
265+ statut : Notification_1 . StatutNotification . EN_COURS ,
266+ } ) ;
267+ await this . notifRepo . save ( emailNotif ) ;
268+ try {
269+ await ( 0 , mailService_1 . sendEmail ) ( destinationEmail , "RICASH NOTIFICATION" , message ) ;
270+ emailNotif . statut = Notification_1 . StatutNotification . ENVOYEE ;
271+ }
272+ catch ( error ) {
273+ emailNotif . statut = Notification_1 . StatutNotification . ECHEC ;
274+ console . error ( "Erreur d'envoi email :" , error ) ;
275+ }
276+ await this . notifRepo . save ( emailNotif ) ;
277+ }
278+ return {
279+ ...( smsNotif ? { sms : smsNotif } : { } ) ,
280+ ...( emailNotif ? { email : emailNotif } : { } ) ,
281+ } ;
282+ }
161283 // 4. Validation spécifique au canal demandé
162284 if ( data . canal === Notification_1 . CanalNotification . EMAIL && ! destinationEmail ) {
163285 throw new Error ( `Canal EMAIL demandé mais aucune adresse email valide pour l'utilisateur ${ data . utilisateurId } ` ) ;
0 commit comments