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.appointment.service;
35
36 import java.sql.Date;
37 import java.time.DayOfWeek;
38 import java.time.LocalDate;
39 import java.time.LocalDateTime;
40 import java.time.LocalTime;
41 import java.time.temporal.ChronoUnit;
42 import java.time.temporal.WeekFields;
43 import java.util.ArrayList;
44 import java.util.Comparator;
45 import java.util.HashMap;
46 import java.util.List;
47 import java.util.Locale;
48 import java.util.Map;
49 import java.util.Objects;
50 import java.util.Set;
51 import java.util.concurrent.Executors;
52 import java.util.concurrent.ScheduledExecutorService;
53 import java.util.concurrent.ScheduledFuture;
54 import java.util.concurrent.TimeUnit;
55 import java.util.concurrent.locks.Lock;
56 import java.util.stream.Collectors;
57
58 import javax.servlet.http.HttpServletRequest;
59 import javax.validation.ConstraintViolation;
60
61 import org.apache.commons.collections.CollectionUtils;
62 import org.apache.commons.lang3.StringUtils;
63
64 import fr.paris.lutece.plugins.appointment.business.appointment.Appointment;
65 import fr.paris.lutece.plugins.appointment.business.appointment.AppointmentSlot;
66 import fr.paris.lutece.plugins.appointment.business.category.Category;
67 import fr.paris.lutece.plugins.appointment.business.planning.TimeSlot;
68 import fr.paris.lutece.plugins.appointment.business.planning.WeekDefinition;
69 import fr.paris.lutece.plugins.appointment.business.planning.WorkingDay;
70 import fr.paris.lutece.plugins.appointment.business.rule.ReservationRule;
71 import fr.paris.lutece.plugins.appointment.business.slot.Slot;
72 import fr.paris.lutece.plugins.appointment.business.user.User;
73 import fr.paris.lutece.plugins.appointment.service.lock.SlotEditTask;
74 import fr.paris.lutece.plugins.appointment.web.dto.AppointmentDTO;
75 import fr.paris.lutece.plugins.appointment.web.dto.AppointmentFilterDTO;
76 import fr.paris.lutece.plugins.appointment.web.dto.AppointmentFormDTO;
77 import fr.paris.lutece.plugins.appointment.web.dto.ReservationRuleDTO;
78 import fr.paris.lutece.plugins.appointment.web.dto.ResponseRecapDTO;
79 import fr.paris.lutece.plugins.genericattributes.business.Entry;
80 import fr.paris.lutece.plugins.genericattributes.business.EntryFilter;
81 import fr.paris.lutece.plugins.genericattributes.business.EntryHome;
82 import fr.paris.lutece.plugins.genericattributes.business.GenericAttributeError;
83 import fr.paris.lutece.plugins.genericattributes.business.Response;
84 import fr.paris.lutece.plugins.genericattributes.service.entrytype.EntryTypeServiceManager;
85 import fr.paris.lutece.plugins.genericattributes.service.entrytype.IEntryTypeService;
86 import fr.paris.lutece.plugins.genericattributes.util.GenericAttributesUtils;
87 import fr.paris.lutece.portal.business.user.AdminUser;
88 import fr.paris.lutece.portal.business.user.AdminUserHome;
89 import fr.paris.lutece.portal.service.i18n.I18nService;
90 import fr.paris.lutece.portal.service.rbac.RBACService;
91 import fr.paris.lutece.portal.service.util.AppLogService;
92 import fr.paris.lutece.portal.service.util.AppPropertiesService;
93 import fr.paris.lutece.util.beanvalidation.BeanValidationUtil;
94
95
96
97
98
99
100
101 public final class AppointmentUtilities
102 {
103
104 public static final String ERROR_MESSAGE_EMPTY_CONFIRM_EMAIL = "appointment.validation.appointment.EmailConfirmation.email";
105 public static final String ERROR_MESSAGE_CONFIRM_EMAIL = "appointment.message.error.confirmEmail";
106 public static final String ERROR_MESSAGE_DATE_APPOINTMENT = "appointment.message.error.dateAppointment";
107 public static final String ERROR_MESSAGE_EMPTY_EMAIL = "appointment.validation.appointment.Email.notEmpty";
108 public static final String ERROR_MESSAGE_EMPTY_NB_BOOKED_SEAT = "appointment.validation.appointment.NbBookedSeat.notEmpty";
109 public static final String ERROR_MESSAGE_FORMAT_NB_BOOKED_SEAT = "appointment.validation.appointment.NbBookedSeat.notNumberFormat";
110 public static final String ERROR_MESSAGE_ERROR_NB_BOOKED_SEAT = "appointment.validation.appointment.NbBookedSeat.error";
111
112 public static final String MARK_PERMISSION_ADD_COMMENT = "permission_add_comment";
113 public static final String MARK_PERMISSION_MODERATE_COMMENT = "permission_moderate_comment";
114 public static final String MARK_PERMISSION_ACCESS_CODE = "permission_access_code";
115 public static final String OLD_APPOINTMENT_DTO = "oldAppointment";
116 public static final String SESSION_TASK_TIMER_SLOT = "appointment.session.task.timer.slot";
117
118 public static final String PROPERTY_DEFAULT_EXPIRED_TIME_EDIT_APPOINTMENT = "appointment.edit.expired.time";
119
120 public static final int THIRTY_MINUTES = 30;
121
122
123 private static final ScheduledExecutorService _secheduledExecutor = Executors
124 .newSingleThreadScheduledExecutor( r -> new Thread( r, "Lutece-AppointmentSecheduledExecutor-thread" ) );
125
126
127
128 public static final String CONSTANT_GENERIC_ATTRIBUTE_TYPE_PHONE_NAME = "appointment.entryTypePhone";
129
130 public static final String CONSTANT_PHONE_NUMBERS_SEPARATOR = ", ";
131
132
133
134
135 private AppointmentUtilities( )
136 {
137 }
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153 public static void checkEmail( String strEmail, String strConfirmEmail, AppointmentFormDTO form, Locale locale, List<GenericAttributeError> listFormErrors )
154 {
155 if ( form.getEnableMandatoryEmail( ) )
156 {
157 if ( StringUtils.isEmpty( strEmail ) )
158 {
159 GenericAttributeError genAttError = new GenericAttributeError( );
160 genAttError.setErrorMessage( I18nService.getLocalizedString( ERROR_MESSAGE_EMPTY_EMAIL, locale ) );
161 listFormErrors.add( genAttError );
162 }
163 if ( StringUtils.isEmpty( strConfirmEmail ) )
164 {
165 GenericAttributeError genAttError = new GenericAttributeError( );
166 genAttError.setErrorMessage( I18nService.getLocalizedString( ERROR_MESSAGE_EMPTY_CONFIRM_EMAIL, locale ) );
167 listFormErrors.add( genAttError );
168 }
169 }
170 if ( !StringUtils.equalsIgnoreCase( strEmail, strConfirmEmail ) )
171 {
172 GenericAttributeError genAttError = new GenericAttributeError( );
173 genAttError.setErrorMessage( I18nService.getLocalizedString( ERROR_MESSAGE_CONFIRM_EMAIL, locale ) );
174 listFormErrors.add( genAttError );
175 }
176 }
177
178
179
180
181
182
183
184
185
186
187
188 public static void checkDateOfTheAppointmentIsNotBeforeNow( AppointmentDTO appointmentDTO, Locale locale, List<GenericAttributeError> listFormErrors )
189 {
190 LocalDateTime startingDateTime = getStartingDateTime( appointmentDTO );
191 if ( startingDateTime == null || startingDateTime.toLocalDate( ).isBefore( LocalDate.now( ) ) )
192 {
193 GenericAttributeError genAttError = new GenericAttributeError( );
194 genAttError.setErrorMessage( I18nService.getLocalizedString( ERROR_MESSAGE_DATE_APPOINTMENT, locale ) );
195 listFormErrors.add( genAttError );
196 }
197 }
198
199
200
201
202
203
204
205
206
207
208
209
210 public static boolean checkNbDaysBetweenTwoAppointments( AppointmentDTO appointmentDTO, String strEmail, AppointmentFormDTO form )
211 {
212 boolean bCheckPassed = true;
213 int nbDaysBetweenTwoAppointments = form.getNbDaysBeforeNewAppointment( );
214 if ( nbDaysBetweenTwoAppointments != 0 )
215 {
216 List<Slot> listSlots = getSlotsByEmail( strEmail, appointmentDTO.getIdAppointment( ) );
217 if ( CollectionUtils.isNotEmpty( listSlots ) )
218 {
219
220 listSlots = listSlots.stream( ).filter( s -> s.getIdForm( ) == form.getIdForm( ) ).collect( Collectors.toList( ) );
221 if ( CollectionUtils.isNotEmpty( listSlots ) )
222 {
223 LocalDateTime dateOfTheLastAppointment = listSlots.stream( ).map( Slot::getStartingDateTime ).max( LocalDateTime::compareTo )
224 .orElse( null );
225
226
227
228 LocalDateTime dateOfTheAppointment = getStartingDateTime( appointmentDTO );
229 if ( dateOfTheLastAppointment != null && Math
230 .abs( dateOfTheLastAppointment.toLocalDate( ).until( dateOfTheAppointment, ChronoUnit.DAYS ) ) <= nbDaysBetweenTwoAppointments )
231 {
232 bCheckPassed = false;
233 }
234 }
235 }
236 }
237 return bCheckPassed;
238 }
239
240
241
242
243
244
245
246
247
248
249
250
251 public static boolean checkNbDaysBetweenTwoAppointmentsTaken( AppointmentDTO appointmentDTO, String strEmail, AppointmentFormDTO form )
252 {
253 boolean bCheckPassed = true;
254 int nbDaysBetweenTwoAppointments = form.getNbDaysBeforeNewAppointment( );
255 if ( nbDaysBetweenTwoAppointments != 0 && StringUtils.isNotEmpty( strEmail ) )
256 {
257 AppointmentFilterDTOweb/dto/AppointmentFilterDTO.html#AppointmentFilterDTO">AppointmentFilterDTO filter = new AppointmentFilterDTO( );
258 filter.setEmail( strEmail );
259 filter.setStatus( 0 );
260 filter.setIdForm( form.getIdForm( ) );
261 List<Appointment> listAppointment = AppointmentService.findListAppointmentsByFilter( filter );
262
263
264 if ( appointmentDTO.getIdAppointment( ) != 0 )
265 {
266 listAppointment.removeIf( a -> a.getIdAppointment( ) != appointmentDTO.getIdAppointment( ) );
267 }
268
269 if ( CollectionUtils.isNotEmpty( listAppointment ) )
270 {
271
272 LocalDateTime dateOfTheLastAppointmentTaken = listAppointment.stream( ).map( Appointment::getDateAppointmentTaken )
273 .max( LocalDateTime::compareTo ).orElse( null );
274
275 if ( dateOfTheLastAppointmentTaken != null
276 && Math.abs( dateOfTheLastAppointmentTaken.until( LocalDateTime.now( ), ChronoUnit.DAYS ) ) < nbDaysBetweenTwoAppointments )
277 {
278 bCheckPassed = false;
279 }
280
281 }
282 }
283 return bCheckPassed;
284 }
285
286
287
288
289
290
291
292
293
294
295 private static List<Appointment> getAppointmentByEmail( String strEmail, int idAppointment )
296 {
297 List<Appointment> listAppointment = new ArrayList<>( );
298 if ( StringUtils.isNotEmpty( strEmail ) )
299 {
300
301 List<User> listUsers = UserService.findUsersByEmail( strEmail );
302 if ( listUsers != null )
303 {
304
305 for ( User user : listUsers )
306 {
307
308 listAppointment.addAll( AppointmentService.findListAppointmentByUserId( user.getIdUser( ) ) );
309 }
310
311
312
313 if ( idAppointment != 0 )
314 {
315 listAppointment = listAppointment.stream( ).filter( a -> a.getIdAppointment( ) != idAppointment ).collect( Collectors.toList( ) );
316 }
317
318 }
319 }
320 return listAppointment;
321 }
322
323
324
325
326
327
328
329
330
331
332 private static List<Slot> getSlotsByEmail( String strEmail, int idAppointment )
333 {
334 List<Slot> listSlots = new ArrayList<>( );
335 if ( StringUtils.isNotEmpty( strEmail ) )
336 {
337 List<Appointment> listAppointment = getAppointmentByEmail( strEmail, idAppointment );
338 if ( CollectionUtils.isNotEmpty( listAppointment ) )
339 {
340
341
342
343
344 for ( Appointment appointment : listAppointment )
345 {
346 if ( !appointment.getIsCancelled( ) )
347 {
348 listSlots = SlotService.findListSlotByIdAppointment( appointment.getIdAppointment( ) );
349 }
350 }
351
352 }
353
354 }
355 return listSlots;
356 }
357
358
359
360
361
362
363
364
365
366
367
368
369 public static boolean checkNbMaxAppointmentsOnAGivenPeriod( AppointmentDTO appointmentDTO, String strEmail, AppointmentFormDTO form )
370 {
371 if ( form.getNbMaxAppointmentsPerUser( ) > 0 && StringUtils.isNotEmpty( strEmail ) )
372 {
373
374 LocalDateTime startingDateTime = getStartingDateTime( appointmentDTO );
375 if ( startingDateTime == null )
376 {
377 AppLogService.error( "Error checkNbMaxAppointmentsOnAGivenPeriod, startingDateTime is null" );
378 return false;
379 }
380 LocalDate dateOfTheAppointment = startingDateTime.toLocalDate( );
381
382 AppointmentFilterDTOweb/dto/AppointmentFilterDTO.html#AppointmentFilterDTO">AppointmentFilterDTO filter = new AppointmentFilterDTO( );
383 filter.setEmail( strEmail );
384 filter.setIdForm( form.getIdForm( ) );
385 filter.setStatus( 0 );
386 if ( form.getNbDaysForMaxAppointmentsPerUser( ) > 0 )
387 {
388 filter.setStartingDateOfSearch( Date.valueOf( dateOfTheAppointment.minusDays( (long) form.getNbDaysForMaxAppointmentsPerUser( ) - 1 ) ) );
389 filter.setEndingDateOfSearch( Date.valueOf( dateOfTheAppointment.plusDays( (long) form.getNbDaysForMaxAppointmentsPerUser( ) - 1 ) ) );
390 }
391 List<AppointmentDTO> listAppointmentsDTO = AppointmentService.findListAppointmentsDTOByFilter( filter );
392
393
394 if ( appointmentDTO.getIdAppointment( ) != 0 )
395 {
396
397 listAppointmentsDTO.removeIf( appt -> appt.getIdAppointment( ) != appointmentDTO.getIdAppointment( ) );
398 }
399
400 if ( CollectionUtils.isNotEmpty( listAppointmentsDTO ) )
401 {
402 if ( form.getNbDaysForMaxAppointmentsPerUser( ) > 0 )
403 {
404
405 List<AppointmentDTO> listAppointmentsBefore = listAppointmentsDTO.stream( )
406 .filter( appt -> appt.getStartingDateTime( ).toLocalDate( ).isBefore( dateOfTheAppointment )
407 || appt.getStartingDateTime( ).toLocalDate( ).isEqual( dateOfTheAppointment ) )
408 .collect( Collectors.toList( ) );
409 List<AppointmentDTO> listAppointmentsAfter = listAppointmentsDTO.stream( )
410 .filter( appt -> appt.getStartingDateTime( ).toLocalDate( ).isAfter( dateOfTheAppointment )
411 || appt.getStartingDateTime( ).toLocalDate( ).isEqual( dateOfTheAppointment ) )
412 .collect( Collectors.toList( ) );
413
414 if ( listAppointmentsBefore.size( ) >= form.getNbMaxAppointmentsPerUser( )
415 || listAppointmentsAfter.size( ) >= form.getNbMaxAppointmentsPerUser( ) )
416 {
417 return false;
418 }
419 }
420 else
421 if ( listAppointmentsDTO.size( ) >= form.getNbMaxAppointmentsPerUser( ) )
422 {
423
424 return false;
425 }
426 }
427 }
428 return true;
429
430 }
431
432
433
434
435
436
437
438
439
440
441
442
443 public static boolean checkNbMaxAppointmentsDefinedOnCategory( AppointmentDTO appointmentDTO, String strEmail, AppointmentFormDTO form,
444 List<AppointmentDTO> listAppointments )
445 {
446 if ( form.getIdCategory( ) != 0 && StringUtils.isNotEmpty( strEmail ) )
447 {
448 Category category = CategoryService.findCategoryById( form.getIdCategory( ) );
449 if ( category != null && category.getNbMaxAppointmentsPerUser( ) > 0 )
450 {
451 LocalDateTime now = LocalDateTime.now( );
452 List<AppointmentDTO> listAppointmentsDTO = AppointmentService.findAppointmentByMailAndCategory( category.getIdCategory( ), strEmail );
453 listAppointmentsDTO.removeIf( appt -> appt.getEndingDateTime( ).isBefore( now ) || appt.getIsCancelled( ) );
454
455
456 if ( appointmentDTO.getIdAppointment( ) != 0 )
457 {
458
459 listAppointmentsDTO.removeIf( appt -> appt.getIdAppointment( ) != appointmentDTO.getIdAppointment( ) );
460 }
461 listAppointments.addAll( listAppointmentsDTO );
462 if ( CollectionUtils.isNotEmpty( listAppointmentsDTO ) && listAppointmentsDTO.size( ) >= category.getNbMaxAppointmentsPerUser( ) )
463 {
464 return false;
465
466 }
467 }
468 }
469 return true;
470
471 }
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488 public static int checkAndReturnNbBookedSeats( String strNbBookedSeats, AppointmentFormDTO form, AppointmentDTO appointmentDTO, Locale locale,
489 List<GenericAttributeError> listFormErrors )
490 {
491 int nbBookedSeats = 1;
492 if ( StringUtils.isEmpty( strNbBookedSeats ) && form.getMaxPeoplePerAppointment( ) > 1 )
493 {
494 GenericAttributeError genAttError = new GenericAttributeError( );
495 genAttError.setErrorMessage( I18nService.getLocalizedString( ERROR_MESSAGE_EMPTY_NB_BOOKED_SEAT, locale ) );
496 listFormErrors.add( genAttError );
497 }
498 if ( StringUtils.isNotEmpty( strNbBookedSeats ) )
499 {
500 try
501 {
502 nbBookedSeats = Integer.parseInt( strNbBookedSeats );
503 }
504 catch( NumberFormatException | NullPointerException e )
505 {
506 GenericAttributeError genAttError = new GenericAttributeError( );
507 genAttError.setErrorMessage( I18nService.getLocalizedString( ERROR_MESSAGE_FORMAT_NB_BOOKED_SEAT, locale ) );
508 listFormErrors.add( genAttError );
509 }
510 }
511
512
513
514
515
516 if ( nbBookedSeats > appointmentDTO.getNbMaxPotentialBookedSeats( ) && !appointmentDTO.getOverbookingAllowed( ) )
517
518 {
519 GenericAttributeError genAttError = new GenericAttributeError( );
520 genAttError.setErrorMessage( I18nService.getLocalizedString( ERROR_MESSAGE_ERROR_NB_BOOKED_SEAT, locale ) );
521 listFormErrors.add( genAttError );
522 }
523
524 if ( nbBookedSeats == 0 )
525 {
526 GenericAttributeError genAttError = new GenericAttributeError( );
527 genAttError.setErrorMessage( I18nService.getLocalizedString( ERROR_MESSAGE_EMPTY_NB_BOOKED_SEAT, locale ) );
528 listFormErrors.add( genAttError );
529 }
530 return nbBookedSeats;
531 }
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547 public static void fillAppointmentDTO( AppointmentDTO appointmentDTO, int nbBookedSeats, String strEmail, String strEmailConfirm, String strFirstName, String strLastName )
548 {
549 appointmentDTO.setDateOfTheAppointment( appointmentDTO.getSlot( ).get( 0 ).getDate( ).format( Utilities.getFormatter( ) ) );
550 appointmentDTO.setNbBookedSeats( nbBookedSeats );
551 appointmentDTO.setEmail( strEmail );
552 appointmentDTO.setConfirmEmail(strEmailConfirm);
553 appointmentDTO.setFirstName( strFirstName );
554 appointmentDTO.setLastName( strLastName );
555 }
556
557
558
559
560
561
562
563
564
565
566
567 public static void validateFormAndEntries( AppointmentDTO appointmentDTO, HttpServletRequest request, List<GenericAttributeError> listFormErrors,
568 boolean allEntries )
569 {
570 Set<ConstraintViolation<AppointmentDTO>> listErrors = BeanValidationUtil.validate( appointmentDTO );
571
572 if ( CollectionUtils.isNotEmpty( listErrors ) )
573 {
574 for ( ConstraintViolation<AppointmentDTO> constraintViolation : listErrors )
575 {
576 GenericAttributeError genAttError = new GenericAttributeError( );
577 genAttError.setErrorMessage( I18nService.getLocalizedString( constraintViolation.getMessageTemplate( ), request.getLocale( ) ) );
578 listFormErrors.add( genAttError );
579 }
580 }
581
582 EntryFilter filter = EntryService.buildEntryFilter( appointmentDTO.getIdForm( ) );
583 if ( allEntries )
584 {
585 filter.setIsOnlyDisplayInBack( GenericAttributesUtils.CONSTANT_ID_NULL );
586 }
587 List<Entry> listEntryFirstLevel = EntryHome.getEntryList( filter );
588 for ( Entry entry : listEntryFirstLevel )
589 {
590 listFormErrors.addAll( EntryService.getResponseEntry( request, entry.getIdEntry( ), request.getLocale( ), appointmentDTO ) );
591 }
592 }
593
594 public static void fillInListResponseWithMapResponse( AppointmentDTO appointmentDTO )
595 {
596 Map<Integer, List<Response>> mapResponses = appointmentDTO.getMapResponsesByIdEntry( );
597 if ( mapResponses != null && !mapResponses.isEmpty( ) )
598 {
599 List<Response> listResponse = new ArrayList<>( );
600 for ( List<Response> listResponseByEntry : mapResponses.values( ) )
601 {
602 listResponse.addAll( listResponseByEntry );
603 }
604 appointmentDTO.setListResponse( listResponse );
605 }
606 }
607
608
609
610
611
612
613
614
615
616
617
618
619 public static List<ResponseRecapDTO> buildListResponse( AppointmentDTO appointment, HttpServletRequest request, Locale locale )
620 {
621 List<ResponseRecapDTO> listResponseRecapDTO = new ArrayList<>( );
622 HashMap<Integer, List<ResponseRecapDTO>> mapResponse = new HashMap<>( );
623 if ( CollectionUtils.isNotEmpty( appointment.getListResponse( ) ) )
624 {
625 listResponseRecapDTO = new ArrayList<>( appointment.getListResponse( ).size( ) );
626 for ( Response response : appointment.getListResponse( ) )
627 {
628 int nIndex = response.getEntry( ).getPosition( );
629 IEntryTypeService entryTypeService = EntryTypeServiceManager.getEntryTypeService( response.getEntry( ) );
630 ResponseRecapDTOo/ResponseRecapDTO.html#ResponseRecapDTO">ResponseRecapDTO responseRecapDTO = new ResponseRecapDTO( response,
631 entryTypeService.getResponseValueForRecap( response.getEntry( ), request, response, locale ) );
632
633 List<ResponseRecapDTO> listResponse = mapResponse.computeIfAbsent( nIndex, ArrayList::new );
634 listResponse.add( responseRecapDTO );
635 }
636 }
637 for ( List<ResponseRecapDTO> listResponse : mapResponse.values( ) )
638 {
639 listResponseRecapDTO.addAll( listResponse );
640 }
641 return listResponseRecapDTO;
642 }
643
644
645
646
647
648
649
650
651
652
653 public static void cancelTaskTimer( HttpServletRequest request, int idSlot )
654 {
655 ScheduledFuture<Slot> task = (ScheduledFuture) request.getSession( ).getAttribute( SESSION_TASK_TIMER_SLOT + idSlot );
656 if ( task != null )
657 {
658 if ( !task.isDone( ) )
659 task.cancel( false );
660 request.getSession( ).removeAttribute( SESSION_TASK_TIMER_SLOT + idSlot );
661 }
662 }
663
664 public static boolean isEditSlotTaskExpiredTime( HttpServletRequest request, int idSlot )
665 {
666 ScheduledFuture<Slot> task = (ScheduledFuture) request.getSession( ).getAttribute( SESSION_TASK_TIMER_SLOT + idSlot );
667 return ( task != null && task.isDone( ) );
668 }
669
670
671
672
673
674
675
676
677
678
679
680
681 public static ScheduledFuture<Slot> putTimerInSession( HttpServletRequest request, int nIdSlot, AppointmentDTO appointmentDTO, int maxPeoplePerAppointment )
682 {
683 Lock lock = SlotSafeService.getLockOnSlot( nIdSlot );
684 lock.lock( );
685 try
686 {
687 Slot slot = SlotService.findSlotById( nIdSlot );
688
689 int nbPotentialRemainingPlaces = slot.getNbPotentialRemainingPlaces( );
690 int nbPotentialPlacesTaken = Math.min( nbPotentialRemainingPlaces, maxPeoplePerAppointment );
691 int nNewNbMaxPotentialBookedSeats = Math.min( nbPotentialPlacesTaken + appointmentDTO.getNbMaxPotentialBookedSeats( ), maxPeoplePerAppointment );
692
693 if ( slot.getNbPotentialRemainingPlaces( ) > 0 )
694 {
695
696 ScheduledFuture<Slot> scheduledFuture = _secheduledExecutor.schedule( new SlotEditTask( slot.getIdSlot( ), nbPotentialPlacesTaken ),
697 AppPropertiesService.getPropertyInt( PROPERTY_DEFAULT_EXPIRED_TIME_EDIT_APPOINTMENT, 1 ), TimeUnit.MINUTES );
698 appointmentDTO.setNbMaxPotentialBookedSeats( nNewNbMaxPotentialBookedSeats );
699 SlotSafeService.decrementPotentialRemainingPlaces( nbPotentialPlacesTaken, slot.getIdSlot( ) );
700
701 request.getSession( ).setAttribute( SESSION_TASK_TIMER_SLOT + slot.getIdSlot( ), scheduledFuture );
702 return scheduledFuture;
703 }
704 appointmentDTO.setNbMaxPotentialBookedSeats( 0 );
705 }
706
707 finally
708 {
709
710 lock.unlock( );
711 }
712 return null;
713 }
714
715
716
717
718
719
720
721
722 public static String [ ] [ ] getPermissions( List<AppointmentFormDTO> listForms, AdminUser user )
723 {
724 String [ ] [ ] retour = new String [ listForms.size( )] [ 6];
725 int nI = 0;
726
727 for ( AppointmentFormDTO tmpForm : listForms )
728 {
729
730 String [ ] strRetour = new String [ 7];
731 strRetour [0] = String.valueOf( RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, String.valueOf( tmpForm.getIdForm( ) ),
732 AppointmentResourceIdService.PERMISSION_VIEW_APPOINTMENT, (fr.paris.lutece.api.user.User) user ) );
733 strRetour [1] = String.valueOf( RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, String.valueOf( tmpForm.getIdForm( ) ),
734 AppointmentResourceIdService.PERMISSION_MODIFY_ADVANCED_SETTING_FORM, (fr.paris.lutece.api.user.User) user ) );
735 strRetour [2] = String.valueOf( RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, String.valueOf( tmpForm.getIdForm( ) ),
736 AppointmentResourceIdService.PERMISSION_MODIFY_FORM, (fr.paris.lutece.api.user.User) user ) );
737 strRetour [3] = String.valueOf( RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, String.valueOf( tmpForm.getIdForm( ) ),
738 AppointmentResourceIdService.PERMISSION_MODIFY_FORM, (fr.paris.lutece.api.user.User) user ) );
739 strRetour [4] = String.valueOf( RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, String.valueOf( tmpForm.getIdForm( ) ),
740 AppointmentResourceIdService.PERMISSION_CHANGE_STATE, (fr.paris.lutece.api.user.User) user ) );
741 strRetour [5] = String.valueOf( RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, String.valueOf( tmpForm.getIdForm( ) ),
742 AppointmentResourceIdService.PERMISSION_DELETE_FORM, (fr.paris.lutece.api.user.User) user ) );
743 retour [nI++] = strRetour;
744 }
745
746 return retour;
747 }
748
749
750
751
752
753
754
755
756 public static LocalTime getMinTimeToDisplay( LocalTime minStartingTime )
757 {
758 LocalTime minStartingTimeToDisplay;
759 if ( minStartingTime.getMinute( ) < THIRTY_MINUTES )
760 {
761 minStartingTimeToDisplay = LocalTime.of( minStartingTime.getHour( ), 0 );
762 }
763 else
764 {
765 minStartingTimeToDisplay = LocalTime.of( minStartingTime.getHour( ), THIRTY_MINUTES );
766 }
767 return minStartingTimeToDisplay;
768 }
769
770
771
772
773
774
775
776
777 public static LocalTime getMaxTimeToDisplay( LocalTime maxEndingTime )
778 {
779 LocalTime maxEndingTimeToDisplay;
780 if ( maxEndingTime.getMinute( ) < THIRTY_MINUTES )
781 {
782 maxEndingTimeToDisplay = LocalTime.of( maxEndingTime.getHour( ), THIRTY_MINUTES );
783 }
784 else
785 {
786 maxEndingTimeToDisplay = LocalTime.of( maxEndingTime.getHour( ) + 1, 0 );
787 }
788 return maxEndingTimeToDisplay;
789 }
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804 public static boolean checkNoAppointmentsImpacted( List<Appointment> listAppointment, int nIdForm, LocalDate dateOfModification,
805 AppointmentFormDTO appointmentForm )
806 {
807 ReservationRule previousReservationRule = ReservationRuleService.findReservationRuleByIdFormAndClosestToDateOfApply( nIdForm, dateOfModification );
808 return checkNoAppointmentsImpacted( listAppointment, nIdForm, previousReservationRule.getIdReservationRule( ), appointmentForm );
809 }
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824 public static boolean checkNoAppointmentsImpacted( List<Appointment> listAppointment, int nIdForm, int nIdreservationRule,
825 AppointmentFormDTO appointmentForm )
826 {
827 boolean bNoAppointmentsImpacted = true;
828
829
830 AppointmentFormDTO previousAppointmentForm = FormService.buildAppointmentForm( nIdForm, nIdreservationRule );
831
832 List<DayOfWeek> previousOpenDays = WorkingDayService.getOpenDays( previousAppointmentForm );
833 List<DayOfWeek> newOpenDays = WorkingDayService.getOpenDays( appointmentForm );
834
835 if ( newOpenDays.containsAll( previousOpenDays ) )
836 {
837
838 }
839 else
840 {
841
842 previousOpenDays.removeAll( newOpenDays );
843
844
845
846 boolean bAppointmentOnOpenDays = false;
847 for ( Appointment appointment : listAppointment )
848 {
849 for ( AppointmentSlot appSlot : appointment.getListAppointmentSlot( ) )
850 {
851
852 Slot tempSlot = SlotService.findSlotById( appSlot.getIdSlot( ) );
853 if ( previousOpenDays.contains( tempSlot.getStartingDateTime( ).getDayOfWeek( ) ) )
854 {
855 bAppointmentOnOpenDays = true;
856 break;
857 }
858 }
859 if ( bAppointmentOnOpenDays )
860 {
861 break;
862 }
863 }
864 bNoAppointmentsImpacted = !bAppointmentOnOpenDays;
865 }
866 LocalTime newStartingTime = LocalTime.parse( appointmentForm.getTimeStart( ) );
867 LocalTime newEndingTime = LocalTime.parse( appointmentForm.getTimeEnd( ) );
868 LocalTime oldStartingTime = LocalTime.parse( previousAppointmentForm.getTimeStart( ) );
869 LocalTime oldEndingTime = LocalTime.parse( previousAppointmentForm.getTimeEnd( ) );
870
871 if ( appointmentForm.getDurationAppointments( ) != previousAppointmentForm.getDurationAppointments( ) )
872 {
873 bNoAppointmentsImpacted = false;
874 }
875
876
877 if ( !newStartingTime.equals( oldStartingTime ) || !newEndingTime.equals( oldEndingTime ) )
878 {
879 bNoAppointmentsImpacted = false;
880 }
881
882 return bNoAppointmentsImpacted;
883 }
884
885
886
887
888
889
890
891
892
893
894 public static boolean checkNoAppointmentsImpacted( List<Slot> listSlotWithAppointment, AppointmentFormDTO appointmentForm )
895 {
896
897
898 AppointmentFormDTO previousAppointmentForm = FormService.buildAppointmentForm( appointmentForm.getIdForm( ), appointmentForm.getIdReservationRule( ) );
899
900 List<DayOfWeek> previousOpenDays = WorkingDayService.getOpenDays( previousAppointmentForm );
901 List<DayOfWeek> newOpenDays = WorkingDayService.getOpenDays( appointmentForm );
902
903 if ( newOpenDays.containsAll( previousOpenDays ) )
904 {
905
906 }
907 else
908 {
909
910 previousOpenDays.removeAll( newOpenDays );
911
912
913
914
915 for ( Slot tempSlot : listSlotWithAppointment )
916 {
917 if ( previousOpenDays.contains( tempSlot.getStartingDateTime( ).getDayOfWeek( ) ) )
918 {
919 return false;
920 }
921 }
922
923 }
924 LocalTime newStartingTime = LocalTime.parse( appointmentForm.getTimeStart( ) );
925 LocalTime newEndingTime = LocalTime.parse( appointmentForm.getTimeEnd( ) );
926 LocalTime oldStartingTime = LocalTime.parse( previousAppointmentForm.getTimeStart( ) );
927 LocalTime oldEndingTime = LocalTime.parse( previousAppointmentForm.getTimeEnd( ) );
928
929 if ( appointmentForm.getDurationAppointments( ) != previousAppointmentForm.getDurationAppointments( ) )
930 {
931 return false;
932 }
933
934
935 return !newStartingTime.equals( oldStartingTime ) || !newEndingTime.equals( oldEndingTime );
936 }
937
938
939
940
941
942
943
944
945
946
947 public static boolean checkNoAppointmentsImpacted( List<Slot> listSlotsImpacted, int idReservationRule )
948 {
949
950 List<WorkingDay> listWorkingDay = WorkingDayService.findListWorkingDayByWeekDefinitionRule( idReservationRule );
951 for ( Slot slot : listSlotsImpacted )
952 {
953 WorkingDay workingDay = listWorkingDay.stream( ).filter( day -> day.getDayOfWeek( ) == slot.getDate( ).getDayOfWeek( ).getValue( ) ).findFirst( )
954 .orElse( null );
955 if ( workingDay != null )
956 {
957
958 if ( workingDay.getListTimeSlot( ).stream( ).noneMatch(
959 time -> slot.getStartingTime( ).equals( time.getStartingTime( ) ) && slot.getEndingTime( ).equals( time.getEndingTime( ) ) ) )
960 {
961
962 return false;
963 }
964
965 }
966 else
967 {
968
969 return false;
970 }
971 }
972
973 return true;
974 }
975
976
977
978
979
980
981
982
983 public static boolean checkNoValidatedAppointmentsOnThisSlot( Slot slot )
984 {
985 boolean bNoValidatedAppointmentsOnThisSlot = true;
986 List<Appointment> listAppointmentsOnThisSlot = AppointmentService.findListAppointmentBySlot( slot.getIdSlot( ) );
987 if ( CollectionUtils.isNotEmpty( listAppointmentsOnThisSlot ) )
988 {
989 listAppointmentsOnThisSlot = listAppointmentsOnThisSlot.stream( ).filter( a -> !a.getIsCancelled( ) ).collect( Collectors.toList( ) );
990 }
991 if ( CollectionUtils.isNotEmpty( listAppointmentsOnThisSlot ) )
992 {
993 bNoValidatedAppointmentsOnThisSlot = false;
994 }
995 return bNoValidatedAppointmentsOnThisSlot;
996 }
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011 public static List<Slot> findSlotsImpactedByThisTimeSlot( TimeSlot timeSlot, int nIdForm, int nIdWeekDefinition, boolean bShiftSlot )
1012 {
1013 List<Slot> listSlotsImpacted = null;
1014
1015 WeekDefinition currentModifiedWeekDefinition = WeekDefinitionService.findWeekDefinitionById( nIdWeekDefinition );
1016
1017 List<Slot> listSlots = SlotService.findSlotsByIdFormAndDateRange( nIdForm, currentModifiedWeekDefinition.getDateOfApply( ).atStartOfDay( ),
1018 currentModifiedWeekDefinition.getEndingDateOfApply( ).atTime( LocalTime.MAX ) );
1019
1020
1021 WorkingDay workingDay = WorkingDayService.findWorkingDayLightById( timeSlot.getIdWorkingDay( ) );
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031 if ( bShiftSlot )
1032 {
1033 listSlotsImpacted = listSlots.stream( )
1034 .filter( slot -> ( ( slot.getStartingDateTime( ).getDayOfWeek( ) == DayOfWeek.of( workingDay.getDayOfWeek( ) ) )
1035 && ( !slot.getStartingTime( ).isBefore( timeSlot.getStartingTime( ) )
1036 || ( slot.getStartingTime( ).isBefore( timeSlot.getStartingTime( ) )
1037 && ( slot.getEndingTime( ).isAfter( timeSlot.getStartingTime( ) ) ) ) ) ) )
1038 .collect( Collectors.toList( ) );
1039 }
1040 else
1041 {
1042 listSlotsImpacted = listSlots.stream( )
1043 .filter( slot -> ( slot.getStartingDateTime( ).getDayOfWeek( ) == DayOfWeek.of( workingDay.getDayOfWeek( ) ) )
1044 && ( slot.getStartingTime( ).equals( timeSlot.getStartingTime( ) )
1045 || ( slot.getStartingTime( ).isBefore( timeSlot.getStartingTime( ) )
1046 && ( slot.getEndingTime( ).isAfter( timeSlot.getStartingTime( ) ) ) )
1047 || ( slot.getStartingTime( ).isAfter( timeSlot.getStartingTime( ) )
1048 && ( !slot.getEndingTime( ).isAfter( timeSlot.getEndingTime( ) ) ) ) ) )
1049 .collect( Collectors.toList( ) );
1050 }
1051
1052 return listSlotsImpacted;
1053 }
1054
1055 public static LocalDateTime getStartingDateTime( Appointment appointmentDTO )
1056 {
1057
1058 List<Slot> listSlot = appointmentDTO.getSlot( );
1059 if ( CollectionUtils.isNotEmpty( listSlot ) )
1060 {
1061 Slot slot = listSlot.stream( ).min( Comparator.comparing( Slot::getStartingDateTime ) ).orElse( listSlot.get( 0 ) );
1062 return slot.getStartingDateTime( );
1063 }
1064
1065 return null;
1066 }
1067
1068 public static LocalDateTime getEndingDateTime( Appointment appointmentDTO )
1069 {
1070
1071 List<Slot> listSlot = appointmentDTO.getSlot( );
1072 if ( listSlot != null && !listSlot.isEmpty( ) )
1073 {
1074
1075 Slot slot = listSlot.stream( ).max( Comparator.comparing( Slot::getStartingDateTime ) ).orElse( listSlot.get( 0 ) );
1076 return slot.getEndingDateTime( );
1077 }
1078
1079 return null;
1080 }
1081
1082
1083
1084
1085
1086
1087
1088
1089 public static boolean isConsecutiveSlots( List<Slot> allSlots )
1090 {
1091 Slot slot = null;
1092 for ( Slot nextSlot : allSlots )
1093 {
1094 if ( nextSlot == null || ( slot != null && !Objects.equals( slot.getEndingDateTime( ), nextSlot.getStartingDateTime( ) ) ) )
1095 {
1096 return false;
1097 }
1098 slot = nextSlot;
1099 }
1100 return true;
1101 }
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112 public static void fillInReservationRuleAdvancedParam( ReservationRuleDTO reservationRuleDTO, AppointmentFormDTO appointmentForm )
1113 {
1114 reservationRuleDTO.setMaxCapacityPerSlot( appointmentForm.getMaxCapacityPerSlot( ) );
1115 reservationRuleDTO.setMaxPeoplePerAppointment( appointmentForm.getMaxPeoplePerAppointment( ) );
1116 reservationRuleDTO.setName( appointmentForm.getName( ) );
1117 reservationRuleDTO.setDescriptionRule( appointmentForm.getDescriptionRule( ) );
1118 reservationRuleDTO.setColor( appointmentForm.getColor( ) );
1119 reservationRuleDTO.setDurationAppointments( appointmentForm.getDurationAppointments( ) );
1120 reservationRuleDTO.setTimeEnd( appointmentForm.getTimeEnd( ) );
1121 reservationRuleDTO.setTimeStart( appointmentForm.getTimeStart( ) );
1122
1123 reservationRuleDTO.setIdForm( appointmentForm.getIdForm( ) );
1124 }
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137 public static boolean weekIsOpenInFO( AppointmentFormDTO appointmentFormDTO, List<WeekDefinition> listWeek, Locale locale )
1138 {
1139
1140 if ( appointmentFormDTO.getIsActive( ) )
1141 {
1142 Date startingValidityDate = appointmentFormDTO.getDateStartValidity( );
1143 LocalDate startingDateOfDisplay = LocalDate.now( );
1144
1145 if ( startingValidityDate != null && startingValidityDate.toLocalDate( ).isAfter( startingDateOfDisplay ) )
1146 {
1147 startingDateOfDisplay = startingValidityDate.toLocalDate( );
1148 }
1149
1150
1151
1152
1153 LocalDate dateOfSunday = startingDateOfDisplay.with( WeekFields.of( locale ).dayOfWeek( ), DayOfWeek.SUNDAY.getValue( ) );
1154 LocalDate endingDateOfDisplay = dateOfSunday.plusWeeks( (long) appointmentFormDTO.getNbWeeksToDisplay( ) - 1 );
1155 Date endingValidityDate = appointmentFormDTO.getDateEndValidity( );
1156 if ( endingValidityDate != null && endingDateOfDisplay.isAfter( endingValidityDate.toLocalDate( ) ) )
1157 {
1158 endingDateOfDisplay = endingValidityDate.toLocalDate( );
1159 }
1160 if ( startingDateOfDisplay.isAfter( endingDateOfDisplay ) )
1161 {
1162
1163 return false;
1164 }
1165
1166 for ( WeekDefinition week : listWeek )
1167 {
1168
1169 if ( ( week.getDateOfApply( ).isBefore( endingDateOfDisplay ) || week.getDateOfApply( ).isEqual( endingDateOfDisplay ) )
1170 && ( week.getEndingDateOfApply( ).isAfter( startingDateOfDisplay ) || week.getEndingDateOfApply( ).isEqual( startingDateOfDisplay ) ) )
1171 {
1172
1173 return true;
1174 }
1175 }
1176 }
1177
1178 return false;
1179 }
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190 public static boolean checkListSlotIsBuildedCorrectly( int nIdForm, List<Slot> listSlots )
1191 {
1192 if ( !CollectionUtils.isEmpty( listSlots ) )
1193 {
1194
1195 LocalDateTime minDate = listSlots.stream( ).map( Slot::getStartingDateTime ).min( LocalDateTime::compareTo ).orElse( null );
1196 LocalDateTime maxDate = listSlots.stream( ).map( Slot::getStartingDateTime ).max( LocalDateTime::compareTo ).orElse( null );
1197 if ( minDate != null && maxDate != null )
1198 {
1199 List<WeekDefinition> listWeekDefinition = WeekDefinitionService.findListWeekDefinition( nIdForm );
1200 Map<WeekDefinition, ReservationRule> mapReservationRule = ReservationRuleService.findAllReservationRule( nIdForm, listWeekDefinition );
1201 List<Slot> listSlotBuilded = SlotService.buildListSlot( nIdForm, mapReservationRule, minDate.toLocalDate( ), maxDate.toLocalDate( ) );
1202 for ( Slot slt : listSlots )
1203 {
1204 if ( listSlotBuilded.stream( ).noneMatch( slot -> slt.getStartingDateTime( ).isEqual( slot.getStartingDateTime( ) )
1205 && slt.getEndingDateTime( ).isEqual( slot.getEndingDateTime( ) ) ) )
1206 {
1207 return false;
1208 }
1209 }
1210 }
1211 }
1212 return true;
1213 }
1214
1215
1216
1217
1218
1219 public static void shutdownSecheduledExecutor( )
1220 {
1221 _secheduledExecutor.shutdown( );
1222 try
1223 {
1224 if ( !_secheduledExecutor.awaitTermination( 60, TimeUnit.SECONDS ) )
1225 {
1226 _secheduledExecutor.shutdownNow( );
1227 }
1228 }
1229 catch( InterruptedException e )
1230 {
1231
1232 AppLogService.error( e.getMessage( ), e );
1233 _secheduledExecutor.shutdownNow( );
1234 Thread.currentThread().interrupt();
1235 }
1236
1237 }
1238
1239
1240
1241
1242
1243
1244
1245
1246 public static AppointmentDTO buildAppointmentDTO( Appointment appointment )
1247 {
1248 AppointmentDTOb/dto/AppointmentDTO.html#AppointmentDTO">AppointmentDTO appointmentDTO = new AppointmentDTO( );
1249 User user = appointment.getUser();
1250
1251 appointmentDTO.setIdForm( appointment.getSlot( ).get( 0 ).getIdForm( ) );
1252 appointmentDTO.setIdUser( appointment.getIdUser( ) );
1253 appointmentDTO.setListAppointmentSlot( appointment.getListAppointmentSlot( ) );
1254 appointmentDTO.setIdAppointment( appointment.getIdAppointment( ) );
1255
1256 if(user != null) {
1257 appointmentDTO.setFirstName( user.getFirstName( ) );
1258 appointmentDTO.setLastName( user.getLastName( ) );
1259 appointmentDTO.setEmail( user.getEmail( ) );
1260 appointmentDTO.setPhoneNumber( user.getPhoneNumber( ) );
1261 appointmentDTO.setGuid( user.getGuid( ) );
1262 appointmentDTO.setReference( appointment.getReference( ) );
1263 }
1264
1265 LocalDateTime startingDateTime = AppointmentUtilities.getStartingDateTime( appointment );
1266 LocalDateTime endingDateTime = AppointmentUtilities.getEndingDateTime( appointment );
1267
1268 appointmentDTO.setStartingDateTime( startingDateTime );
1269 appointmentDTO.setEndingDateTime( endingDateTime );
1270 appointmentDTO.setDateOfTheAppointment( startingDateTime.toLocalDate( ).format( Utilities.getFormatter( ) ) );
1271 appointmentDTO.setStartingTime( startingDateTime.toLocalTime( ) );
1272 appointmentDTO.setEndingTime( endingDateTime.toLocalTime( ) );
1273 appointmentDTO.setIsCancelled( appointment.getIsCancelled( ) );
1274 appointmentDTO.setNbBookedSeats( appointment.getNbPlaces( ) );
1275 appointment.getSlot().forEach(SlotService::addDateAndTimeToSlot);
1276 appointmentDTO.setSlot( appointment.getSlot( ) );
1277 appointmentDTO.setUser( appointment.getUser( ) );
1278
1279 appointmentDTO.setAdminUserCreate( appointment.getAdminUserCreate( ) );
1280 appointmentDTO.setDateAppointmentTaken( appointment.getDateAppointmentTaken( ) );
1281
1282 return appointmentDTO;
1283 }
1284
1285
1286
1287
1288
1289
1290
1291
1292 public static void setAppointmentPhoneNumberValuesFromResponse( AppointmentDTO appointment )
1293 {
1294
1295 List<Response> listAppointmentResponses = appointment.getListResponse( );
1296
1297 if( CollectionUtils.isNotEmpty( listAppointmentResponses ) )
1298 {
1299 try
1300 {
1301
1302 List<String> listPhoneNumbers = listAppointmentResponses.stream( )
1303 .filter( elem -> elem.getEntry( ) != null && elem.getEntry( ).getEntryType( ).getBeanName( ).contentEquals( AppointmentUtilities.CONSTANT_GENERIC_ATTRIBUTE_TYPE_PHONE_NAME ) )
1304 .map( Response::getResponseValue )
1305 .filter( value -> value != null && !value.trim( ).isEmpty( ) )
1306 .map( String::trim )
1307 .collect( Collectors.toList( ) );
1308
1309 if( !listPhoneNumbers.isEmpty( ) )
1310 {
1311
1312 String strPhoneNumbers = StringUtils.join( listPhoneNumbers, CONSTANT_PHONE_NUMBERS_SEPARATOR );
1313 appointment.setPhoneNumber( strPhoneNumbers );
1314 }
1315 }
1316 catch ( NullPointerException e)
1317 {
1318 AppLogService.error( "Error when retrieving appointment's phone number value", e );
1319 }
1320 }
1321 }
1322 }