1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package fr.paris.lutece.plugins.genericalert.service;
35
36 import java.sql.Timestamp;
37 import java.time.format.DateTimeFormatter;
38 import java.util.ArrayList;
39 import java.util.Calendar;
40 import java.util.Date;
41 import java.util.GregorianCalendar;
42 import java.util.List;
43 import java.util.Locale;
44 import java.util.concurrent.TimeUnit;
45
46 import javax.inject.Inject;
47 import javax.inject.Named;
48 import javax.servlet.http.HttpServletRequest;
49
50 import org.apache.commons.lang3.StringUtils;
51
52 import fr.paris.lutece.plugins.appointment.business.appointment.Appointment;
53 import fr.paris.lutece.plugins.appointment.business.localization.Localization;
54 import fr.paris.lutece.plugins.appointment.business.user.User;
55 import fr.paris.lutece.plugins.appointment.service.AppointmentResponseService;
56 import fr.paris.lutece.plugins.appointment.service.AppointmentService;
57 import fr.paris.lutece.plugins.appointment.service.FormService;
58 import fr.paris.lutece.plugins.appointment.service.LocalizationService;
59 import fr.paris.lutece.plugins.appointment.service.UserService;
60 import fr.paris.lutece.plugins.appointment.service.entrytype.EntryTypePhone;
61 import fr.paris.lutece.plugins.appointment.web.AppointmentApp;
62 import fr.paris.lutece.plugins.appointment.web.dto.AppointmentDTO;
63 import fr.paris.lutece.plugins.genericalert.business.ReminderAppointment;
64 import fr.paris.lutece.plugins.genericalert.business.TaskNotifyReminderConfig;
65 import fr.paris.lutece.plugins.genericalert.business.TaskNotifyReminderConfigHome;
66 import fr.paris.lutece.plugins.genericattributes.business.Entry;
67 import fr.paris.lutece.plugins.genericattributes.business.EntryFilter;
68 import fr.paris.lutece.plugins.genericattributes.business.EntryHome;
69 import fr.paris.lutece.plugins.genericattributes.business.Response;
70 import fr.paris.lutece.plugins.genericattributes.business.ResponseHome;
71 import fr.paris.lutece.plugins.genericattributes.service.entrytype.EntryTypeServiceManager;
72 import fr.paris.lutece.plugins.genericattributes.service.entrytype.IEntryTypeService;
73 import fr.paris.lutece.plugins.workflow.utils.WorkflowUtils;
74 import fr.paris.lutece.plugins.workflowcore.business.action.Action;
75 import fr.paris.lutece.plugins.workflowcore.business.resource.ResourceHistory;
76 import fr.paris.lutece.plugins.workflowcore.business.resource.ResourceWorkflow;
77 import fr.paris.lutece.plugins.workflowcore.business.state.State;
78 import fr.paris.lutece.plugins.workflowcore.service.action.IActionService;
79 import fr.paris.lutece.plugins.workflowcore.service.config.ITaskConfigService;
80 import fr.paris.lutece.plugins.workflowcore.service.resource.IResourceHistoryService;
81 import fr.paris.lutece.plugins.workflowcore.service.resource.IResourceWorkflowService;
82 import fr.paris.lutece.plugins.workflowcore.service.state.StateService;
83 import fr.paris.lutece.plugins.workflowcore.service.task.ITask;
84 import fr.paris.lutece.plugins.workflowcore.service.task.ITaskService;
85 import fr.paris.lutece.plugins.workflowcore.service.task.SimpleTask;
86 import fr.paris.lutece.plugins.workflowcore.service.workflow.IWorkflowService;
87 import fr.paris.lutece.portal.service.i18n.I18nService;
88 import fr.paris.lutece.portal.service.mail.MailService;
89 import fr.paris.lutece.portal.service.spring.SpringContextService;
90 import fr.paris.lutece.portal.service.util.AppException;
91 import fr.paris.lutece.portal.service.util.AppLogService;
92 import fr.paris.lutece.portal.service.util.AppPropertiesService;
93 import fr.paris.lutece.portal.web.l10n.LocaleService;
94
95
96
97
98
99
100
101 public class TaskNotifyReminder extends SimpleTask
102 {
103
104
105 private static final String MARK_FIRST_NAME = "${firstName}";
106 private static final String MARK_LAST_NAME = "${lastName}";
107 private static final String MARK_DATE_APP = "${date_appointment}";
108 private static final String MARK_TIME_APP = "${time_appointment}";
109 private static final String MARK_LOCALIZATION = "${localisation}";
110 private static final String MARK_CANCEL_APP = "${url_cancel}";
111 private static final String DEFAULT_PREFIX_SENDER = "@contact-everyone.fr";
112 private static final String DEFAULT_SENDER_SMS = "magali.lemaire@paris.fr";
113 private static final String MARK_REGEX_SMS = "^(06|07)[0-9]{8}$";
114 private static final String USER_AUTO = "auto";
115 private static final String MARK_DURATION_LIMIT = "daemon.reminder.interval";
116
117
118 private static final String PROPERTY_MAIL_SENDER_NAME = "genericalert.task_notify_reminder.mailSenderName";
119 private static final String PROPERTY_SENDER_SMS = "genericalert.senderSms";
120 private static final String PROPERTY_PREFIX_SMS_SENDER = "genericalert.prefixSenderSms";
121
122 private static final String MESSAGE_MARK_DESCRIPTION = "genericalert.task_notify_reminder.description";
123
124 public static final String FORMAT_TIME = "HH:mm";
125
126
127 private final StateService _stateService = SpringContextService.getBean( StateService.BEAN_SERVICE );
128 @Inject
129 @Named( TaskNotifyReminderConfigService.BEAN_SERVICE )
130 private ITaskConfigService _taskNotifyReminderConfigService;
131
132 @Inject
133 private IActionService _actionService;
134
135 @Inject
136 private ITaskService _taskService;
137
138 @Inject
139 private IResourceHistoryService _resourceHistoryService;
140
141 @Inject
142 private IResourceWorkflowService _resourceWorkflowService;
143
144 IWorkflowService _workflowService = SpringContextService.getBean( fr.paris.lutece.plugins.workflowcore.service.workflow.WorkflowService.BEAN_SERVICE );
145
146 @Override
147 public void processTask( int nIdResourceHistory, HttpServletRequest request, Locale locale )
148 {
149
150
151 }
152
153 public void sendReminder( int nIdResource, String strResourceType, int nIdAction, int nIdWorkflow )
154 {
155 ITask task = null;
156 List<ITask> listActionTasks = _taskService.getListTaskByIdAction( nIdAction, Locale.getDefault( ) );
157 for ( ITask tsk : listActionTasks )
158 {
159 if ( tsk.getTaskType( ) != null && tsk.getTaskType( ).getBeanName( ) != null
160 && tsk.getTaskType( ).getBeanName( ).equals( "genericalert.taskNotifyReminder" ) )
161 {
162 task = tsk;
163 }
164 }
165 if ( task != null )
166 {
167 Action action = _actionService.findByPrimaryKey( nIdAction );
168 TaskNotifyReminderConfig config = null;
169 Date date = new Date( );
170 Calendar calendar = new GregorianCalendar( );
171 calendar.setTime( date );
172 Timestamp timestampDay = new Timestamp( calendar.getTimeInMillis( ) );
173 AppointmentDTO appointment = AppointmentService.buildAppointmentDTOFromIdAppointment( nIdResource );
174
175 if ( appointment != null )
176 {
177 config = TaskNotifyReminderConfigHome.findByIdForm( task.getId( ), appointment.getIdForm( ) );
178 }
179
180 if ( config != null )
181 {
182 for ( int stateBefore : action.getListIdStateBefore( ) ) {
183 List<ReminderAppointment> listReminders = null;
184 if ( FormService.findFormLightByPrimaryKey( appointment.getIdForm( ) ).getIsActive( ) )
185 {
186 Timestamp timeStartDate = Timestamp.valueOf( appointment.getStartingDateTime( ) );
187 State stateAppointment = _stateService.findByResource( appointment.getIdAppointment( ), Appointment.APPOINTMENT_RESOURCE_TYPE,
188 nIdWorkflow );
189 if ( timeStartDate.getTime( ) > timestampDay.getTime( ) && stateAppointment != null && stateAppointment.getId( ) == stateBefore )
190 {
191 long minutes = Math.abs( TimeUnit.MILLISECONDS.toMinutes( timestampDay.getTime( ) - timeStartDate.getTime( ) ) );
192
193
194
195
196
197 if ( config.getNbAlerts( ) > 0 )
198 {
199 listReminders = config.getListReminderAppointment( );
200 }
201
202 for ( ReminderAppointment reminder : listReminders )
203 {
204 sendReminder( appointment, reminder, timeStartDate, minutes, nIdWorkflow, config, strResourceType, nIdAction );
205 }
206 }
207 }
208 }
209 }
210 }
211 }
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228 private void sendReminder( AppointmentDTO appointment, ReminderAppointment reminder, Date startAppointment, long nDiffMin, int nIdWorkflow,
229 TaskNotifyReminderConfig config, String strResourceType, int nIdAction )
230 {
231 int nInterval = Integer.parseInt( AppPropertiesService.getProperty( MARK_DURATION_LIMIT ) );
232
233 long nMinTime = ( reminder.getTimeToAlert( ) * 60 * 24 ) - nInterval;
234 long nMaxTime = ( reminder.getTimeToAlert( ) * 60 * 24 ) + nInterval;
235
236 if ( nDiffMin <= nMaxTime && nDiffMin >= nMinTime
237 && ( ( appointment.getNotification( ) == 0 ) || ( appointment.getNotification( ) != ( reminder.getRank( ) ) ) ) )
238 {
239 boolean bNotified = false;
240 Locale locale = LocaleService.getDefault( );
241 String strSenderMail = MailService.getNoReplyEmail( );
242 String strSenderName = I18nService.getLocalizedString( PROPERTY_MAIL_SENDER_NAME, locale );
243 String strEmailCc = reminder.getEmailCc( );
244
245 String strEmailText = reminder.getEmailAlertMessage( );
246 String strSmsText = reminder.getSmsAlertMessage( );
247
248 if ( strEmailText != null && !strEmailText.isEmpty( ) )
249 {
250 strEmailText = getMessageAppointment( strEmailText, appointment );
251 }
252 if ( strSmsText != null && !strSmsText.isEmpty( ) )
253 {
254 strSmsText = getMessageAppointment( strSmsText, appointment );
255 }
256 User user = UserService.findUserById( appointment.getIdUser( ) );
257 if ( reminder.isEmailNotify( ) && !StringUtils.isEmpty( user.getEmail( ) ) )
258 {
259 try
260 {
261 MailService.sendMailHtml( user.getEmail( ), strEmailCc, StringUtils.EMPTY, strSenderName, strSenderMail, reminder.getAlertSubject( ),
262 strEmailText );
263 bNotified = true;
264 }
265 catch( Exception e )
266 {
267 AppLogService.info( "CATCH sending MAIL" );
268 AppLogService.error( "AppointmentReminderDaemon - Error sending reminder alert MAIL to : {}", e.getMessage( ), e );
269 }
270 }
271
272 if ( reminder.isSmsNotify( ) && reminder.getNumberPhone( ) != null )
273 {
274 String strRecipient = getSmsFromAppointment( appointment, reminder );
275
276 if ( !strRecipient.isEmpty( ) && strRecipient.matches( MARK_REGEX_SMS ) )
277 {
278 try
279 {
280
281 String strDefaultRecipientSms = AppPropertiesService.getProperty( PROPERTY_PREFIX_SMS_SENDER, DEFAULT_PREFIX_SENDER );
282 String strSenderSms = AppPropertiesService.getProperty( PROPERTY_SENDER_SMS, DEFAULT_SENDER_SMS );
283
284 strRecipient += strDefaultRecipientSms;
285
286 MailService.sendMailHtml( strRecipient, strSenderName, strSenderSms, reminder.getAlertSubject( ), strSmsText );
287 bNotified = true;
288 }
289 catch( Exception e )
290 {
291 AppLogService.info( "CATCH sending reminder alert SMS: " );
292 AppLogService.error( "AppointmentReminderDaemon - Error sending reminder alert SMS to : {} {}", strRecipient, e.getMessage( ), e );
293 }
294 }
295 }
296 if ( bNotified )
297 {
298 appointment.setNotification( reminder.getRank( ) );
299 try
300 {
301 AppointmentService.updateAppointment( appointment );
302 doChangeState( config, reminder, nIdWorkflow, appointment );
303 }
304 catch( Exception e )
305 {
306 AppLogService.info( "CATCH CHANGING STATE : " );
307 throw new AppException( e.getMessage( ), e );
308
309 }
310 }
311 }
312 }
313
314
315
316
317
318
319
320
321
322
323 private String getSmsFromAppointment( AppointmentDTO appointment, ReminderAppointment reminder )
324 {
325 String strPhoneNumber = StringUtils.EMPTY;
326 EntryFilter entryFilter = new EntryFilter( );
327 entryFilter.setIdResource( appointment.getIdForm( ) );
328
329 List<Integer> listIdResponse = AppointmentResponseService.findListIdResponse( appointment.getIdAppointment( ) );
330 List<Response> listResponses = new ArrayList<>( listIdResponse.size( ) );
331 for ( int nIdResponse : listIdResponse )
332 {
333 Response response = ResponseHome.findByPrimaryKey( nIdResponse );
334 if ( response != null )
335 {
336 listResponses.add( response );
337 }
338 }
339
340 List<Entry> listEntries = EntryHome.getEntryList( entryFilter );
341 for ( Entry entry : listEntries )
342 {
343 IEntryTypeService entryTypeService = EntryTypeServiceManager.getEntryTypeService( entry );
344
345 if ( entryTypeService instanceof EntryTypePhone )
346 {
347 for ( Response response : listResponses )
348 {
349 if ( ( response.getEntry( ).getIdEntry( ) == entry.getIdEntry( ) ) && StringUtils.isNotBlank( response.getResponseValue( ) )
350 && entry.getTitle( ).equals( reminder.getNumberPhone( ) ) )
351 {
352 strPhoneNumber = response.getResponseValue( );
353
354 break;
355 }
356 }
357
358 if ( StringUtils.isNotEmpty( strPhoneNumber ) )
359 {
360 break;
361 }
362 }
363 }
364 return strPhoneNumber;
365 }
366
367
368
369
370
371
372
373
374
375
376 private String getMessageAppointment( String msg, AppointmentDTO appointment )
377 {
378 DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern( FORMAT_TIME );
379 String strText = StringUtils.EMPTY;
380 User user = UserService.findUserById( appointment.getIdUser( ) );
381 Localization localization = LocalizationService.findLocalizationWithFormId( appointment.getIdForm( ) );
382 String strLocation = StringUtils.EMPTY;
383 if ( localization != null && localization.getAddress( ) != null )
384 {
385 strLocation = localization.getAddress( );
386 }
387 strText = msg.replace( MARK_FIRST_NAME, user.getFirstName( ) );
388 strText = strText.replace( MARK_LAST_NAME, user.getLastName( ) );
389 strText = strText.replace( MARK_DATE_APP, appointment.getDateOfTheAppointment( ) );
390 strText = strText.replace( MARK_TIME_APP, appointment.getStartingDateTime( ).format( timeFormatter ) );
391 strText = strText.replace( MARK_LOCALIZATION, strLocation );
392 strText = strText.replace( MARK_CANCEL_APP, AppointmentApp.getCancelAppointmentUrl( appointment ) );
393
394 return strText;
395 }
396
397
398
399
400
401
402
403
404
405
406
407
408 private void doChangeState( TaskNotifyReminderConfig config, ReminderAppointment reminder, int nIdWorkflow, Appointment appointment )
409 {
410 Locale locale = I18nService.getDefaultLocale( );
411 ITask task = _taskService.findByPrimaryKey( config.getIdTask( ), locale );
412
413 if ( task != null )
414 {
415
416 State state = _stateService.findByPrimaryKey( reminder.getIdStateAfter( ) );
417 Action action = _actionService.findByPrimaryKey( task.getAction( ).getId( ) );
418
419 if ( ( state != null ) && ( action != null ) )
420 {
421
422
423 ResourceHistory resourceHistory = new ResourceHistory( );
424 resourceHistory.setIdResource( appointment.getIdAppointment( ) );
425 resourceHistory.setResourceType( Appointment.APPOINTMENT_RESOURCE_TYPE );
426 resourceHistory.setAction( action );
427 resourceHistory.setWorkFlow( action.getWorkflow( ) );
428 resourceHistory.setCreationDate( WorkflowUtils.getCurrentTimestamp( ) );
429 resourceHistory.setUserAccessCode( USER_AUTO );
430 _resourceHistoryService.create( resourceHistory );
431
432
433 ResourceWorkflow resourceWorkflow = _resourceWorkflowService.findByPrimaryKey( appointment.getIdAppointment( ),
434 Appointment.APPOINTMENT_RESOURCE_TYPE, nIdWorkflow );
435
436 resourceWorkflow.setState( state );
437 _resourceWorkflowService.update( resourceWorkflow );
438
439
440 _workflowService.doProcessAutomaticReflexiveActions( appointment.getIdAppointment( ), Appointment.APPOINTMENT_RESOURCE_TYPE, state.getId( ),
441 null, locale );
442 }
443 }
444 }
445
446
447
448
449 @Override
450 public void doRemoveConfig( )
451 {
452 _taskNotifyReminderConfigService.remove( this.getId( ) );
453 }
454
455 @Override
456 public String getTitle( Locale locale )
457 {
458 return I18nService.getLocalizedString( MESSAGE_MARK_DESCRIPTION, locale );
459 }
460
461 }