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.web;
35
36 import java.time.DayOfWeek;
37 import java.time.LocalDate;
38 import java.time.LocalDateTime;
39 import java.time.LocalTime;
40 import java.time.temporal.TemporalField;
41 import java.time.temporal.WeekFields;
42 import java.util.ArrayList;
43 import java.util.Comparator;
44 import java.util.HashMap;
45 import java.util.LinkedHashMap;
46 import java.util.List;
47 import java.util.Locale;
48 import java.util.Map;
49 import java.util.Set;
50 import java.util.StringJoiner;
51 import java.util.stream.Collectors;
52 import java.util.stream.Stream;
53
54 import javax.servlet.http.HttpServletRequest;
55
56 import fr.paris.lutece.portal.business.file.File;
57 import fr.paris.lutece.portal.service.file.FileService;
58 import fr.paris.lutece.portal.service.file.IFileStoreServiceProvider;
59 import org.apache.commons.codec.binary.Base64;
60 import org.apache.commons.collections.CollectionUtils;
61 import org.apache.commons.lang3.StringUtils;
62
63 import fr.paris.lutece.plugins.appointment.business.appointment.Appointment;
64 import fr.paris.lutece.plugins.appointment.business.appointment.AppointmentSlot;
65 import fr.paris.lutece.plugins.appointment.business.calendar.CalendarTemplate;
66 import fr.paris.lutece.plugins.appointment.business.calendar.CalendarTemplateHome;
67 import fr.paris.lutece.plugins.appointment.business.form.Form;
68 import fr.paris.lutece.plugins.appointment.business.message.FormMessage;
69 import fr.paris.lutece.plugins.appointment.business.planning.WeekDefinition;
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.exception.AppointmentSavedException;
73 import fr.paris.lutece.plugins.appointment.exception.SlotEditTaskExpiredTimeException;
74 import fr.paris.lutece.plugins.appointment.exception.SlotFullException;
75 import fr.paris.lutece.plugins.appointment.log.LogUtilities;
76 import fr.paris.lutece.plugins.appointment.service.AppointmentResponseService;
77 import fr.paris.lutece.plugins.appointment.service.AppointmentService;
78 import fr.paris.lutece.plugins.appointment.service.AppointmentUtilities;
79 import fr.paris.lutece.plugins.appointment.service.EntryService;
80 import fr.paris.lutece.plugins.appointment.service.FormMessageService;
81 import fr.paris.lutece.plugins.appointment.service.FormService;
82 import fr.paris.lutece.plugins.appointment.service.ReservationRuleService;
83 import fr.paris.lutece.plugins.appointment.service.SlotSafeService;
84 import fr.paris.lutece.plugins.appointment.service.SlotService;
85 import fr.paris.lutece.plugins.appointment.service.UserService;
86 import fr.paris.lutece.plugins.appointment.service.Utilities;
87 import fr.paris.lutece.plugins.appointment.service.WeekDefinitionService;
88 import fr.paris.lutece.plugins.appointment.service.listeners.AppointmentListenerManager;
89 import fr.paris.lutece.plugins.appointment.service.upload.AppointmentAsynchronousUploadHandler;
90 import fr.paris.lutece.plugins.appointment.web.dto.AppointmentDTO;
91 import fr.paris.lutece.plugins.appointment.web.dto.AppointmentFilterDTO;
92 import fr.paris.lutece.plugins.appointment.web.dto.AppointmentFormDTO;
93 import fr.paris.lutece.plugins.genericattributes.business.Entry;
94 import fr.paris.lutece.plugins.genericattributes.business.GenericAttributeError;
95 import fr.paris.lutece.plugins.genericattributes.business.Response;
96 import fr.paris.lutece.plugins.workflowcore.service.task.ITask;
97 import fr.paris.lutece.plugins.workflowcore.service.task.ITaskService;
98 import fr.paris.lutece.plugins.workflowcore.service.task.TaskService;
99 import fr.paris.lutece.portal.service.accesscontrol.AccessControlService;
100 import fr.paris.lutece.portal.service.admin.AccessDeniedException;
101 import fr.paris.lutece.portal.service.captcha.CaptchaSecurityService;
102 import fr.paris.lutece.portal.service.i18n.I18nService;
103 import fr.paris.lutece.portal.service.image.ImageResource;
104 import fr.paris.lutece.portal.service.message.SiteMessageException;
105 import fr.paris.lutece.portal.service.security.LuteceUser;
106 import fr.paris.lutece.portal.service.security.SecurityService;
107 import fr.paris.lutece.portal.service.security.UserNotSignedException;
108 import fr.paris.lutece.portal.service.spring.SpringContextService;
109 import fr.paris.lutece.portal.service.template.AppTemplateService;
110 import fr.paris.lutece.portal.service.util.AppLogService;
111 import fr.paris.lutece.portal.service.util.AppPathService;
112 import fr.paris.lutece.portal.service.util.AppPropertiesService;
113 import fr.paris.lutece.portal.service.workflow.WorkflowService;
114 import fr.paris.lutece.portal.util.mvc.commons.annotations.Action;
115 import fr.paris.lutece.portal.util.mvc.commons.annotations.View;
116 import fr.paris.lutece.portal.util.mvc.utils.MVCMessage;
117 import fr.paris.lutece.portal.util.mvc.utils.MVCUtils;
118 import fr.paris.lutece.portal.util.mvc.xpage.MVCApplication;
119 import fr.paris.lutece.portal.util.mvc.xpage.annotations.Controller;
120 import fr.paris.lutece.portal.web.xpages.XPage;
121 import fr.paris.lutece.util.ErrorMessage;
122 import fr.paris.lutece.util.html.HtmlTemplate;
123 import fr.paris.lutece.util.url.UrlItem;
124
125
126
127
128
129
130
131 @Controller( xpageName = AppointmentApp.XPAGE_NAME, pageTitleI18nKey = AppointmentApp.MESSAGE_DEFAULT_PAGE_TITLE, pagePathI18nKey = AppointmentApp.MESSAGE_DEFAULT_PATH )
132 public class AppointmentApp extends MVCApplication
133 {
134
135
136
137
138 public static final String MESSAGE_DEFAULT_PATH = "appointment.appointment.name";
139
140
141
142
143 public static final String MESSAGE_DEFAULT_PAGE_TITLE = "appointment.appointmentApp.defaultTitle";
144
145
146
147
148 protected static final String XPAGE_NAME = "appointment";
149
150
151
152
153 private static final long serialVersionUID = 5741361182728887387L;
154
155
156 private static final String TEMPLATE_APPOINTMENT_FORM_LIST = "/skin/plugins/appointment/appointment_form_list.html";
157 private static final String TEMPLATE_APPOINTMENT_FORM = "/skin/plugins/appointment/appointment_form.html";
158 private static final String TEMPLATE_APPOINTMENT_FORM_RECAP = "/skin/plugins/appointment/appointment_form_recap.html";
159 private static final String TEMPLATE_APPOINTMENT_CREATED = "skin/plugins/appointment/appointment_created.html";
160 private static final String TEMPLATE_CANCEL_APPOINTMENT = "skin/plugins/appointment/cancel_appointment.html";
161 private static final String TEMPLATE_APPOINTMENT_CANCELED = "skin/plugins/appointment/appointment_canceled.html";
162 private static final String TEMPLATE_MY_APPOINTMENTS = "skin/plugins/appointment/my_appointments.html";
163 private static final String TEMPLATE_HTML_CODE_FORM = "skin/plugins/appointment/html_code_form.html";
164 private static final String TEMPLATE_HTML_CODE_NB_PLACES_TO_TAKE_FORM = "skin/plugins/appointment/appointment_nb_places_to_take_form.html";
165 private static final String TEMPLATE_TASKS_FORM_WORKFLOW = "skin/plugins/appointment/tasks_form_workflow.html";
166 private static final String TEMPLATE_ERROR_APPOINTMENT_REFERENCE = "skin/plugins/appointment/error_appointment_reference.html";
167
168
169 public static final String VIEW_APPOINTMENT_FORM = "getViewAppointmentForm";
170 public static final String VIEW_APPOINTMENT_CALENDAR = "getViewAppointmentCalendar";
171 private static final String VIEW_APPOINTMENT_FORM_LIST = "getViewFormList";
172 private static final String VIEW_DISPLAY_RECAP_APPOINTMENT = "displayRecapAppointment";
173 private static final String VIEW_GET_APPOINTMENT_CREATED = "getAppointmentCreated";
174 private static final String VIEW_APPOINTMENT_CANCELED = "getAppointmentCanceled";
175 private static final String VIEW_GET_MY_APPOINTMENTS = "getMyAppointments";
176 private static final String VIEW_GET_VIEW_CANCEL_APPOINTMENT = "getViewCancelAppointment";
177 private static final String VIEW_WORKFLOW_ACTION_FORM = "viewWorkflowActionForm";
178 private static final String VIEW_CHANGE_DATE_APPOINTMENT = "viewChangeDateAppointment";
179
180
181 private static final String ACTION_DO_VALIDATE_FORM = "doValidateForm";
182 private static final String ACTION_DO_MAKE_APPOINTMENT = "doMakeAppointment";
183 private static final String ACTION_DO_CANCEL_APPOINTMENT = "doCancelAppointment";
184 private static final String ACTION_DO_PROCESS_WORKFLOW_ACTION = "doProcessWorkflowAction";
185
186
187 private static final String PARAMETER_STARTING_DATE_TIME = "starting_date_time";
188 private static final String PARAMETER_ENDING_DATE_OF_DISPLAY = "ending_date_of_display";
189 private static final String PARAMETER_STR_ENDING_DATE_OF_DISPLAY = "str_ending_date_of_display";
190 private static final String PARAMETER_DATE_OF_DISPLAY = "date_of_display";
191 private static final String PARAMETER_DAY_OF_WEEK = "dow";
192 private static final String PARAMETER_HIDDEN_DAYS = "hidden_days";
193 private static final String PARAMETER_ID_FORM = "id_form";
194 private static final String PARAMETER_EVENTS = "events";
195 private static final String PARAMETER_MIN_DURATION = "min_duration";
196 private static final String PARAMETER_MIN_TIME = "min_time";
197 private static final String PARAMETER_MAX_TIME = "max_time";
198 private static final String PARAMETER_EMAIL = "email";
199 private static final String PARAMETER_EMAIL_CONFIRMATION = "emailConfirm";
200 private static final String PARAMETER_FIRST_NAME = "firstname";
201 private static final String PARAMETER_LAST_NAME = "lastname";
202 private static final String PARAMETER_NUMBER_OF_BOOKED_SEATS = "nbBookedSeats";
203 private static final String PARAMETER_BACK = "back";
204 private static final String PARAMETER_REF_APPOINTMENT = "refAppointment";
205 private static final String PARAMETER_FROM_MY_APPOINTMENTS = "fromMyappointments";
206 private static final String PARAMETER_REFERER = "referer";
207 private static final String PARAMETER_WEEK_VIEW = "week_view";
208 private static final String PARAMETER_DAY_VIEW = "day_view";
209 private static final String PARAMETER_ANCHOR = "anchor";
210 private static final String PARAMETER_MODIFICATION_FORM = "mod";
211 private static final String PARAMETER_MIN_DATE_OF_OPEN_DAY = "min_date_of_open_day";
212 private static final String PARAMETER_MAX_DATE_OF_OPEN_DAY = "max_date_of_open_day";
213 private static final String PARAMETER_IS_MODIFICATION = "is_modification";
214 private static final String PARAMETER_NB_PLACE_TO_TAKE = "nbPlacesToTake";
215 private static final String PARAMETER_ID_ACTION = "id_action";
216 private static final String PARAMETER_MODIF_DATE = "modif_date";
217
218
219 private static final String MARK_MODIFICATION_DATE_APPOINTMENT = "modifDateAppointment";
220 private static final String MARK_NBPLACESTOTAKE = "nbPlacesToTake";
221 private static final String MARK_MAX_NBPLACESTOTAKE = "maxNbPlacesToTake";
222 private static final String MARK_INFOS = "infos";
223 private static final String MARK_LOCALE = "locale";
224 private static final String MARK_FORM = "form";
225 private static final String MARK_USER = "user";
226 private static final String MARK_FORM_MESSAGES = "formMessages";
227 private static final String MARK_STR_ENTRY = "str_entry";
228 private static final String MARK_APPOINTMENT = "appointment";
229 private static final String MARK_LIST_ERRORS = "listAllErrors";
230 private static final String MARK_PLACES = "nbplaces";
231 private static final String MARK_DATE_APPOINTMENT = "dateAppointment";
232 private static final String MARK_STARTING_TIME_APPOINTMENT = "startingTimeAppointment";
233 private static final String MARK_ENDING_TIME_APPOINTMENT = "endingTimeAppointment";
234 private static final String MARK_FORM_LIST = "form_list";
235 private static final String MARK_FORM_HTML = "form_html";
236 private static final String MARK_FORM_NB_PLACES_TO_TAKE_HTML = "mark_nb_places_to_take_form";
237 private static final String MARK_FORM_ERRORS = "form_errors";
238 private static final String MARK_FORM_CALENDAR_ERRORS = "formCalendarErrors";
239 private static final String MARK_CAPTCHA = "captcha";
240 private static final String MARK_REF = "%%REF%%";
241 private static final String MARK_DATE_APP = "%%DATE%%";
242 private static final String MARK_TIME_BEGIN = "%%HEURE_DEBUT%%";
243 private static final String MARK_TIME_END = "%%HEURE_FIN%%";
244 private static final String MARK_LIST_APPOINTMENTS = "list_appointments";
245 private static final String MARK_BACK_URL = "backUrl";
246 private static final String MARK_FROM_URL = "fromUrl";
247 private static final String MARK_LIST_RESPONSE_RECAP_DTO = "listResponseRecapDTO";
248 private static final String MARK_DATA = "data";
249 private static final String MARK_BASE_64 = "base64";
250 private static final String MARK_SEMI_COLON = ";";
251 private static final String MARK_COMMA = ",";
252 private static final String MARK_COLON = ":";
253 private static final String MARK_ICONS = "icons";
254 private static final String MARK_ICON_NULL = "NULL";
255 private static final String MARK_ANCHOR = "#";
256 private static final String MARK_APPOINTMENT_ALREADY_CANCELLED = "alreadyCancelled";
257 private static final String MARK_NO_APPOINTMENT_WITH_THIS_REFERENCE = "noAppointmentWithThisReference";
258 private static final String MARK_APPOINTMENT_PASSED = "appointmentPassed";
259 private static final String MARK_TASKS_FORM = "tasks_form";
260 private static final String MARK_LOCALE_DATE_TIME = "localeDateTime";
261 private static final String MARK_USER_PREFERRED_NAME = "preferred_user_name";
262
263
264 private static final String ERROR_MESSAGE_SLOT_FULL = "appointment.message.error.slotFull";
265 private static final String ERROR_MESSAGE_SLOT_EDIT_TASK_EXPIRED_TIME = "appointment.message.error.appointment.edit.expired.time";
266 private static final String ERROR_MESSAGE_CAPTCHA = "portal.admin.message.wrongCaptcha";
267 private static final String ERROR_MESSAGE_NB_MIN_DAYS_BETWEEN_TWO_APPOINTMENTS = "appointment.validation.appointment.NbMinDaysBetweenTwoAppointments.error";
268 private static final String ERROR_MESSAGE_NB_MAX_APPOINTMENTS_ON_A_PERIOD = "appointment.validation.appointment.NbMaxAppointmentsOnAPeriod.error";
269 private static final String ERROR_MESSAGE_NB_MAX_APPOINTMENTS_ON_A_CATEGORY = "appointment.validation.appointment.NbMaxAppointmentsOnCategory.error";
270 private static final String ERROR_MESSAGE_FORM_NOT_ACTIVE = "appointment.validation.appointment.formNotActive";
271 private static final String ERROR_MESSAGE_NO_STARTING_VALIDITY_DATE = "appointment.validation.appointment.noStartingValidityDate";
272 private static final String ERROR_MESSAGE_FORM_NO_MORE_VALID = "appointment.validation.appointment.formNoMoreValid";
273 private static final String ERROR_MESSAGE_REPORT_APPOINTMENT = "appointment.message.error.report.appointment";
274 private static final String ERROR_MESSAGE_NO_AVAILABLE_SLOT = "appointment.validation.appointment.noAvailableSlot";
275
276 private static final String ERROR_MESSAGE_NB_PLACE_TO_TAKE_TO_BIG = "appointment.message.error.nbplacestotake.toobig";
277
278
279 private static final String MESSAGE_CANCEL_APPOINTMENT_PAGE_TITLE = "appointment.cancelAppointment.pageTitle";
280 private static final String MESSAGE_MY_APPOINTMENTS_PAGE_TITLE = "appointment.myAppointments.name";
281 private static final String MESSAGE_WF_ACTION_SUCESS = "appointment.wf.action.success";
282
283
284 private static final String PROPERTY_USER_ATTRIBUTE_FIRST_NAME = "appointment.userAttribute.firstName";
285 private static final String PROPERTY_USER_ATTRIBUTE_LAST_NAME = "appointment.userAttribute.lastName";
286 private static final String PROPERTY_USER_ATTRIBUTE_PREFERED_NAME = "appointment.userAttribute.preferred_username";
287 private static final String PROPERTY_USER_ATTRIBUTE_EMAIL = "appointment.userAttribute.email";
288 private static final String AGENDA_WEEK = "agendaWeek";
289 private static final String BASIC_WEEK = "basicWeek";
290 private static final String AGENDA_DAY = "agendaDay";
291 private static final String BASIC_DAY = "basicDay";
292 private static final String STEP_3 = "step3";
293
294
295 private transient CaptchaSecurityService _captchaSecurityService;
296 private int _nNbPlacesToTake;
297 private String _strNbPlacesToTakeLength;
298 private AppointmentFormDTO _appointmentForm;
299 private AppointmentDTO _notValidatedAppointment;
300 private AppointmentDTO _validatedAppointment;
301
302
303
304
305
306
307
308
309 @SuppressWarnings( "unchecked" )
310 @View( VIEW_APPOINTMENT_CALENDAR )
311 public synchronized XPage getViewAppointmentCalendar( HttpServletRequest request ) throws AccessDeniedException
312 {
313 Map<String, Object> model = getModel( );
314 Locale locale = getLocale( request );
315 _nNbPlacesToTake = 0;
316
317 int nIdForm = Integer.parseInt( request.getParameter( PARAMETER_ID_FORM ) );
318 String nbPlacesToTake = request.getParameter( PARAMETER_NB_PLACE_TO_TAKE );
319 String refAppointment = request.getParameter( PARAMETER_REF_APPOINTMENT );
320
321 _appointmentForm = FormService.buildAppointmentFormWithoutReservationRule( nIdForm );
322 _strNbPlacesToTakeLength = String.valueOf(_appointmentForm.getNbConsecutiveSlots());
323 boolean bError = false;
324 if ( !_appointmentForm.getIsActive( ) )
325 {
326 addError( ERROR_MESSAGE_FORM_NOT_ACTIVE, locale );
327 bError = true;
328 }
329
330 FormMessage formMessages = FormMessageService.findFormMessageByIdForm( nIdForm );
331
332 if ( StringUtils.isNotEmpty( refAppointment ) )
333 {
334
335 AppointmentDTO appointmentDTO = AppointmentService.buildAppointmentDTOFromRefAppointment( refAppointment );
336
337 if( appointmentDTO == null )
338 {
339
340 return getXPage( TEMPLATE_ERROR_APPOINTMENT_REFERENCE, locale, model );
341 }
342 if ( appointmentDTO.getIsCancelled( ) || appointmentDTO.getStartingDateTime( ).isBefore( LocalDateTime.now( ) ) )
343 {
344 addError( ERROR_MESSAGE_REPORT_APPOINTMENT, locale );
345 bError = true;
346 }
347 else
348 {
349 _validatedAppointment = appointmentDTO;
350 AppointmentService.addAppointmentResponses( _validatedAppointment );
351 nbPlacesToTake = Integer.toString( _validatedAppointment.getNbBookedSeats( ) );
352 }
353 }
354 LocalDate startingDateOfDisplay = LocalDate.now( );
355
356
357 LocalDate startingValidityDate = null;
358 if ( _appointmentForm.getDateStartValidity( ) == null )
359 {
360 addError( ERROR_MESSAGE_NO_STARTING_VALIDITY_DATE, locale );
361 bError = true;
362 }
363 else
364 {
365 startingValidityDate = _appointmentForm.getDateStartValidity( ).toLocalDate( );
366 }
367 if ( startingValidityDate != null && startingValidityDate.isAfter( startingDateOfDisplay ) )
368 {
369 startingDateOfDisplay = startingValidityDate;
370 }
371
372 int nNbWeeksToDisplay = _appointmentForm.getNbWeeksToDisplay( );
373
374
375
376
377 TemporalField fieldISO = WeekFields.of( locale ).dayOfWeek( );
378 LocalDate dateOfSunday = startingDateOfDisplay.with( fieldISO, DayOfWeek.SUNDAY.getValue( ) );
379 LocalDate endingDateOfDisplay = dateOfSunday.plusWeeks( (long) nNbWeeksToDisplay - 1 );
380
381
382
383
384 LocalDate endingValidityDate = null;
385 if ( _appointmentForm.getDateEndValidity( ) != null )
386 {
387 endingValidityDate = _appointmentForm.getDateEndValidity( ).toLocalDate( );
388 if ( endingDateOfDisplay.isAfter( endingValidityDate ) )
389 {
390 endingDateOfDisplay = endingValidityDate;
391 }
392 if ( startingDateOfDisplay.isAfter( endingDateOfDisplay ) )
393 {
394 addError( ERROR_MESSAGE_FORM_NO_MORE_VALID, locale );
395 bError = true;
396 }
397 }
398
399 String strDateOfDisplay = request.getParameter( PARAMETER_DATE_OF_DISPLAY );
400 LocalDate dateOfDisplay = startingDateOfDisplay;
401 if ( StringUtils.isNotEmpty( strDateOfDisplay ) )
402 {
403 dateOfDisplay = LocalDate.parse( strDateOfDisplay );
404 }
405
406 List<WeekDefinition> listWeekDefinition = WeekDefinitionService.findWeekDefinitionByDateOfApply( nIdForm, startingDateOfDisplay, endingDateOfDisplay );
407
408 Map<WeekDefinition, ReservationRule> mapReservationRule = ReservationRuleService.findAllReservationRule( nIdForm, listWeekDefinition );
409 List<ReservationRule> listReservationRules = new ArrayList<>( mapReservationRule.values( ) );
410
411 LocalTime minStartingTime = WeekDefinitionService.getMinStartingTimeOfAListOfWeekDefinition( listReservationRules );
412
413 LocalTime maxEndingTime = WeekDefinitionService.getMaxEndingTimeOfAListOfWeekDefinition( listReservationRules );
414
415
416 List<String> listStrBase0OpenDaysOfWeek = new ArrayList<>(
417 WeekDefinitionService.getSetDaysOfWeekOfAListOfWeekDefinitionForFullCalendar( listReservationRules ) );
418
419 List<Slot> listSlots = new ArrayList<>( );
420 if ( !bError )
421 {
422 boolean isNewNbPlacesToTake = ( nbPlacesToTake != null && StringUtils.isNumeric( nbPlacesToTake ) );
423 if ( _appointmentForm.getIsMultislotAppointment( ) && ( _nNbPlacesToTake != 0 || isNewNbPlacesToTake ) )
424 {
425 _nNbPlacesToTake = isNewNbPlacesToTake ? Integer.parseInt( nbPlacesToTake ) : _nNbPlacesToTake;
426 listSlots = SlotService.buildListSlot( nIdForm, mapReservationRule, startingDateOfDisplay, endingDateOfDisplay, _nNbPlacesToTake );
427
428 }
429 else
430 {
431 _nNbPlacesToTake = 0;
432 listSlots = SlotService.buildListSlot( nIdForm, mapReservationRule, startingDateOfDisplay, endingDateOfDisplay );
433 }
434
435 if ( _nNbPlacesToTake > Integer.parseInt( _strNbPlacesToTakeLength ) )
436 {
437 addError( ERROR_MESSAGE_NB_PLACE_TO_TAKE_TO_BIG, locale );
438 }
439
440
441 XPage accessControlPage = AccessControlService.getInstance( ).doExecuteAccessControl(
442 request,
443 nIdForm,
444 Form.RESOURCE_TYPE,
445 null
446 );
447 if ( accessControlPage != null )
448 {
449 return accessControlPage;
450 }
451
452
453 int minTimeBeforeAppointment = _appointmentForm.getMinTimeBeforeAppointment( );
454 LocalDateTime dateTimeBeforeAppointment = LocalDateTime.now( ).plusHours( minTimeBeforeAppointment );
455
456 if ( CollectionUtils.isNotEmpty( listSlots ) )
457 {
458 listSlots = listSlots.stream( ).filter( s -> s.getStartingDateTime( ).isAfter( dateTimeBeforeAppointment ) ).collect( Collectors.toList( ) );
459 }
460
461
462
463
464 if ( _validatedAppointment != null )
465 {
466 int nbBookedSeats = _validatedAppointment.getNbBookedSeats( );
467 listSlots = listSlots.stream( ).filter( s -> s.getNbPotentialRemainingPlaces( ) >= nbBookedSeats && s.getIsOpen( ) )
468 .collect( Collectors.toList( ) );
469 model.put( MARK_MODIFICATION_DATE_APPOINTMENT, true );
470 model.put( PARAMETER_REF_APPOINTMENT, refAppointment );
471 }
472 else
473 {
474 model.put( MARK_MODIFICATION_DATE_APPOINTMENT, false );
475 }
476
477 LocalDate firstDateOfFreeOpenSlot = null;
478 if ( CollectionUtils.isNotEmpty( listSlots ) )
479 {
480
481 List<Slot> listAvailableSlots = listSlots.stream( ).filter( s -> ( s.getNbPotentialRemainingPlaces( ) > 0 && s.getIsOpen( ) == Boolean.TRUE ) )
482 .collect( Collectors.toList( ) );
483 if ( CollectionUtils.isNotEmpty( listAvailableSlots ) )
484 {
485 firstDateOfFreeOpenSlot = listAvailableSlots.stream( ).min( ( s1, s2 ) -> s1.getStartingDateTime( ).compareTo( s2.getStartingDateTime( ) ) )
486 .get( ).getDate( );
487 }
488 }
489 if (firstDateOfFreeOpenSlot == null) {
490 if (formMessages != null && StringUtils.isNotEmpty(formMessages.getNoAvailableSlot())) {
491 addError(formMessages.getNoAvailableSlot());
492 } else {
493 addError(ERROR_MESSAGE_NO_AVAILABLE_SLOT, locale);
494 }
495 bError = true;
496 }
497
498 if ( firstDateOfFreeOpenSlot != null && firstDateOfFreeOpenSlot.isAfter( dateOfDisplay ) )
499 {
500 dateOfDisplay = firstDateOfFreeOpenSlot;
501 }
502 }
503 if ( bError )
504 {
505 model.put( MARK_FORM_CALENDAR_ERRORS, bError );
506 }
507 if ( formMessages != null && StringUtils.isNotEmpty( formMessages.getCalendarDescription( ) ) )
508 {
509 List<ErrorMessage> listInfos = (List<ErrorMessage>) model.get( MARK_INFOS );
510 if ( listInfos == null )
511 {
512 listInfos = new ArrayList<>( );
513 model.put( MARK_INFOS, listInfos );
514 }
515 MVCMessage message = new MVCMessage( formMessages.getCalendarDescription( ) );
516 listInfos.add( message );
517 }
518
519 CalendarTemplate calendarTemplate = CalendarTemplateHome.findByPrimaryKey( _appointmentForm.getCalendarTemplateId( ) );
520 List<String> listHiddenDays = Stream.of( "0", "1", "2", "3", "4", "5", "6" ).collect( Collectors.toList( ) );
521
522
523
524
525 String dayView = null;
526 String weekView = null;
527 switch( calendarTemplate.getTitle( ) )
528 {
529 case CalendarTemplate.FREE_SLOTS:
530
531 listSlots = listSlots.stream( ).filter( s -> ( ( s.getNbRemainingPlaces( ) > 0 ) && ( s.getIsOpen( ) ) ) ).collect( Collectors.toList( ) );
532 listHiddenDays.clear( );
533 dayView = BASIC_DAY;
534 weekView = BASIC_WEEK;
535 break;
536 case CalendarTemplate.FREE_SLOTS_GROUPED:
537
538 listHiddenDays.clear( );
539 dayView = BASIC_DAY;
540 weekView = BASIC_WEEK;
541 break;
542 case CalendarTemplate.CALENDAR_OPEN_DAYS:
543
544 listHiddenDays.removeAll( listStrBase0OpenDaysOfWeek );
545 dayView = AGENDA_DAY;
546 weekView = AGENDA_WEEK;
547 break;
548 case CalendarTemplate.FREE_SLOTS_ON_OPEN_DAYS:
549
550 listSlots = listSlots.stream( ).filter( s -> ( ( s.getNbRemainingPlaces( ) > 0 ) && ( s.getIsOpen( ) ) ) ).collect( Collectors.toList( ) );
551
552 listHiddenDays.removeAll( listStrBase0OpenDaysOfWeek );
553 dayView = BASIC_DAY;
554 weekView = BASIC_WEEK;
555 break;
556 case CalendarTemplate.CALENDAR:
557 default:
558 listHiddenDays.clear( );
559 dayView = AGENDA_DAY;
560 weekView = AGENDA_WEEK;
561 break;
562 }
563
564
565 Set<Integer> setOpenDays = WeekDefinitionService.getOpenDaysOfWeek( listReservationRules );
566 model.put( PARAMETER_MIN_DATE_OF_OPEN_DAY,
567 LocalDate.now( ).with( DayOfWeek.of( setOpenDays.stream( ).min( Comparator.naturalOrder( ) ).orElse( 1 ) ) ) );
568 model.put( PARAMETER_MAX_DATE_OF_OPEN_DAY,
569 endingDateOfDisplay.with( DayOfWeek.of( setOpenDays.stream( ).max( Comparator.naturalOrder( ) ).orElse( 1 ) ) ) );
570
571 model.put( MARK_FORM, _appointmentForm );
572 model.put( PARAMETER_ID_FORM, nIdForm );
573 model.put( MARK_FORM_MESSAGES, formMessages );
574 model.put( PARAMETER_ENDING_DATE_OF_DISPLAY, endingDateOfDisplay );
575 model.put( PARAMETER_STR_ENDING_DATE_OF_DISPLAY, endingDateOfDisplay.format( Utilities.getFormatter( ) ) );
576 model.put( PARAMETER_DATE_OF_DISPLAY, dateOfDisplay );
577 model.put( PARAMETER_DAY_OF_WEEK, listStrBase0OpenDaysOfWeek );
578 model.put( PARAMETER_MIN_TIME, AppointmentUtilities.getMinTimeToDisplay( minStartingTime ) );
579 model.put( PARAMETER_MAX_TIME, AppointmentUtilities.getMaxTimeToDisplay( maxEndingTime ) );
580 model.put( PARAMETER_MIN_DURATION, LocalTime.MIN.plusMinutes( AppointmentUtilities.THIRTY_MINUTES ) );
581 model.put( MARK_NBPLACESTOTAKE, _nNbPlacesToTake );
582 model.put( PARAMETER_EVENTS, listSlots );
583 model.put( PARAMETER_HIDDEN_DAYS, listHiddenDays );
584 model.put( PARAMETER_DAY_VIEW, dayView );
585 model.put( PARAMETER_WEEK_VIEW, weekView );
586 model.put( MARK_MAX_NBPLACESTOTAKE, Integer.valueOf( _strNbPlacesToTakeLength ) );
587 HtmlTemplate templateNbPlacesToTakeForm = AppTemplateService.getTemplate( TEMPLATE_HTML_CODE_NB_PLACES_TO_TAKE_FORM, locale, model );
588 model.put( MARK_FORM_NB_PLACES_TO_TAKE_HTML, templateNbPlacesToTakeForm.getHtml( ) );
589
590 return getXPage( calendarTemplate.getTemplatePath( ), locale, model );
591 }
592
593
594
595
596
597
598
599
600
601 @View( VIEW_APPOINTMENT_FORM )
602 public synchronized XPage getViewAppointmentForm( HttpServletRequest request ) throws UserNotSignedException, AccessDeniedException
603 {
604 String strIdForm = request.getParameter( PARAMETER_ID_FORM );
605 String strNbPlacesToTake = request.getParameter( PARAMETER_NB_PLACE_TO_TAKE );
606 String strModifDateAppointment = request.getParameter( PARAMETER_MODIF_DATE );
607
608 if ( strModifDateAppointment != null && Boolean.parseBoolean( strModifDateAppointment ) && _validatedAppointment != null
609 && _validatedAppointment.getIdAppointment( ) != 0 )
610 {
611 return getViewChangeDateAppointment( request );
612 }
613 if ( strNbPlacesToTake != null )
614 {
615 _nNbPlacesToTake = Integer.parseInt( strNbPlacesToTake );
616 }
617
618 int nIdForm = Integer.parseInt( strIdForm );
619 if ( _appointmentForm == null || _appointmentForm.getIdForm( ) != nIdForm )
620 {
621 _appointmentForm = FormService.buildAppointmentFormWithoutReservationRule( nIdForm );
622 }
623 if ( !_appointmentForm.getIsActive( ) )
624 {
625 addError( ERROR_MESSAGE_FORM_NOT_ACTIVE, getLocale( request ) );
626 return redirect( request, VIEW_APPOINTMENT_CALENDAR, PARAMETER_ID_FORM, nIdForm, PARAMETER_NB_PLACE_TO_TAKE, _nNbPlacesToTake );
627 }
628 if(!_appointmentForm.getIsMultislotAppointment())
629 {
630 _nNbPlacesToTake = 0;
631 }
632 checkMyLuteceAuthentication( _appointmentForm, request );
633
634 String secondAttempt = request.getParameter( "secondAttempt" );
635 boolean bTestSecondAttempt = Boolean.FALSE;
636 if ( StringUtils.isNotEmpty( secondAttempt ) )
637 {
638 bTestSecondAttempt = Boolean.TRUE;
639 }
640
641 String anchor = request.getParameter( PARAMETER_ANCHOR );
642 if ( StringUtils.isNotEmpty( anchor ) )
643 {
644 LinkedHashMap<String, String> additionalParameters = new LinkedHashMap<>( );
645 additionalParameters.put( PARAMETER_ID_FORM, strIdForm );
646 additionalParameters.put( PARAMETER_STARTING_DATE_TIME, request.getParameter( PARAMETER_STARTING_DATE_TIME ) );
647 additionalParameters.put( PARAMETER_NB_PLACE_TO_TAKE, Integer.toString( _nNbPlacesToTake ) );
648 additionalParameters.put( PARAMETER_ANCHOR, MARK_ANCHOR + anchor );
649 return redirect( request, VIEW_APPOINTMENT_FORM, additionalParameters );
650
651 }
652
653 String isModification = request.getParameter( PARAMETER_IS_MODIFICATION );
654 boolean bModificationForm = false;
655 List<Slot> listSlot = null;
656 if ( isModification != null )
657
658 {
659 bModificationForm = true;
660
661 }
662 else
663 {
664
665 int nNbConsecutiveSlot = ( _nNbPlacesToTake == 0 ) ? 1 : _nNbPlacesToTake;
666 LocalDateTime startingDateTime = LocalDateTime.parse( request.getParameter( PARAMETER_STARTING_DATE_TIME ) );
667 if ( !isAuthorizedDate( startingDateTime, getLocale( request ) ) )
668 {
669
670 addError( ERROR_MESSAGE_SLOT_FULL, getLocale( request ) );
671 return redirect( request, VIEW_APPOINTMENT_CALENDAR, PARAMETER_ID_FORM, nIdForm, PARAMETER_NB_PLACE_TO_TAKE, _nNbPlacesToTake );
672 }
673
674 List<WeekDefinition> listWeekDefinition = WeekDefinitionService.findListWeekDefinition( nIdForm );
675 Map<WeekDefinition, ReservationRule> mapReservationRule = ReservationRuleService.findAllReservationRule( nIdForm, listWeekDefinition );
676
677 listSlot = SlotService.buildListSlot( nIdForm, mapReservationRule, startingDateTime.toLocalDate( ), startingDateTime.toLocalDate( ) );
678 listSlot = listSlot.stream( ).filter(
679 s -> ( ( startingDateTime.compareTo( s.getStartingDateTime( ) ) <= 0 ) && ( s.getNbRemainingPlaces( ) > 0 ) && ( s.getIsOpen( ) ) ) )
680 .limit( nNbConsecutiveSlot ).collect( Collectors.toList( ) );
681
682 if ( listSlot == null || listSlot.stream( ).noneMatch( slot -> slot.getStartingDateTime( ).isEqual( startingDateTime ) )
683 || ( _nNbPlacesToTake > 0 && listSlot.size( ) != _nNbPlacesToTake ) || !AppointmentUtilities.isConsecutiveSlots( listSlot ) )
684 {
685 addError( ERROR_MESSAGE_SLOT_FULL, getLocale( request ) );
686 return redirect( request, VIEW_APPOINTMENT_CALENDAR, PARAMETER_ID_FORM, nIdForm, PARAMETER_NB_PLACE_TO_TAKE, _nNbPlacesToTake );
687 }
688
689 }
690
691 if ( _notValidatedAppointment == null || _notValidatedAppointment.getIdForm( ) != _appointmentForm.getIdForm( ) )
692 {
693 if ( _validatedAppointment != null && _validatedAppointment.getIdForm( ) == _appointmentForm.getIdForm( ) )
694 {
695
696
697
698
699 _notValidatedAppointment = _validatedAppointment;
700 _validatedAppointment = null;
701 }
702 else
703 {
704
705 _notValidatedAppointment = new AppointmentDTO( );
706 }
707 }
708 if ( !bModificationForm )
709 {
710
711 boolean bool = true;
712 _notValidatedAppointment.setIdForm( nIdForm );
713 _notValidatedAppointment.setSlot( null );
714 _notValidatedAppointment.setNbMaxPotentialBookedSeats( 0 );
715 for ( Slot slot : listSlot )
716 {
717
718
719 if ( slot.getIdSlot( ) == 0 )
720 {
721 slot = SlotSafeService.createSlot( slot );
722 }
723 else
724 {
725 slot = SlotService.findSlotById( slot.getIdSlot( ) );
726 }
727
728
729
730 if ( !bTestSecondAttempt && slot.getNbPotentialRemainingPlaces( ) == 0 )
731 {
732 _notValidatedAppointment = null;
733 addError( ERROR_MESSAGE_SLOT_FULL, getLocale( request ) );
734 return redirect( request, VIEW_APPOINTMENT_CALENDAR, PARAMETER_ID_FORM, nIdForm, PARAMETER_NB_PLACE_TO_TAKE, _nNbPlacesToTake );
735 }
736
737 _notValidatedAppointment.addSlot( slot );
738
739 if ( bool )
740 {
741 _notValidatedAppointment.setDateOfTheAppointment( slot.getDate( ).format( Utilities.getFormatter( ) ) );
742 if ( SecurityService.getInstance( ).getRegisteredUser( request ) != null )
743 {
744 setUserInfo( request, _notValidatedAppointment );
745 }
746 FormService.fillAppointmentFormWithReservationRulePart( _appointmentForm,
747 ReservationRuleService.findReservationRuleByIdFormAndClosestToDateOfApply( nIdForm, slot.getDate( ) ) );
748 bool = false;
749 }
750 AppointmentUtilities.putTimerInSession( request, slot.getIdSlot( ), _notValidatedAppointment, _appointmentForm.getMaxPeoplePerAppointment( ) );
751 }
752 if ( _notValidatedAppointment.getNbMaxPotentialBookedSeats( ) == 0 )
753 {
754 addError( ERROR_MESSAGE_SLOT_FULL, getLocale( request ) );
755 return redirect( request, VIEW_APPOINTMENT_CALENDAR, PARAMETER_ID_FORM, nIdForm, PARAMETER_NB_PLACE_TO_TAKE, _nNbPlacesToTake );
756 }
757 }
758 else
759 {
760
761 if ( StringUtils.isEmpty( request.getParameter( PARAMETER_MODIFICATION_FORM ) ) )
762 {
763 LinkedHashMap<String, String> additionalParameters = new LinkedHashMap<>( );
764 additionalParameters.put( PARAMETER_ID_FORM, strIdForm );
765 additionalParameters.put( PARAMETER_MODIFICATION_FORM, String.valueOf( Boolean.TRUE ) );
766 additionalParameters.put( PARAMETER_IS_MODIFICATION, String.valueOf( Boolean.TRUE ) );
767 additionalParameters.put( PARAMETER_ANCHOR, MARK_ANCHOR + STEP_3 );
768 return redirect( request, VIEW_APPOINTMENT_FORM, additionalParameters );
769 }
770 }
771 Map<String, Object> model = getModel( );
772 Locale locale = getLocale( request );
773 StringBuilder strBuffer = new StringBuilder( );
774 List<Entry> listEntryFirstLevel = EntryService.getFilter( _appointmentForm.getIdForm( ), true );
775 for ( Entry entry : listEntryFirstLevel )
776 {
777 EntryService.getHtmlEntry( model, entry.getIdEntry( ), strBuffer, locale, true, _notValidatedAppointment );
778 }
779 FormMessage formMessages = FormMessageService.findFormMessageByIdForm( nIdForm );
780
781 if ( _nNbPlacesToTake != 0 )
782 {
783
784 _notValidatedAppointment.setNbBookedSeats( _nNbPlacesToTake );
785 }
786 model.put( MARK_APPOINTMENT, _notValidatedAppointment );
787 model.put( MARK_NBPLACESTOTAKE, _nNbPlacesToTake );
788 model.put( PARAMETER_DATE_OF_DISPLAY, _notValidatedAppointment.getSlot( ).get( 0 ).getDate( ) );
789 model.put( MARK_FORM, _appointmentForm );
790 model.put( MARK_FORM_MESSAGES, formMessages );
791 model.put( MARK_STR_ENTRY, strBuffer.toString( ) );
792 model.put( MARK_LOCALE, locale );
793 model.put( MARK_PLACES, _notValidatedAppointment.getNbMaxPotentialBookedSeats( ) );
794 model.put( MARK_LIST_ERRORS, AppointmentDTO.getAllErrors( locale ) );
795 LuteceUser user = SecurityService.getInstance( ).getRegisteredUser( request );
796 if( user != null )
797 {
798 model.put( MARK_USER, user );
799 model.put( MARK_USER_PREFERRED_NAME, user.getUserInfo( AppPropertiesService.getProperty( PROPERTY_USER_ATTRIBUTE_PREFERED_NAME, StringUtils.EMPTY ) ) );
800 }
801 else
802 {
803 model.put( MARK_USER, null );
804 }
805
806
807 XPage accessControlPage = AccessControlService.getInstance( ).doExecuteAccessControl(
808 request,
809 nIdForm,
810 Form.RESOURCE_TYPE,
811 null
812 );
813 if ( accessControlPage != null )
814 {
815 return accessControlPage;
816 }
817
818 HtmlTemplate templateForm = AppTemplateService.getTemplate( TEMPLATE_HTML_CODE_FORM, locale, model );
819 model.put( MARK_FORM_HTML, templateForm.getHtml( ) );
820 XPage xPage = getXPage( TEMPLATE_APPOINTMENT_FORM, locale, model );
821
822 if ( _appointmentForm.getDisplayTitleFo( ) )
823 {
824 xPage.setTitle( _appointmentForm.getTitle( ) );
825 }
826 return xPage;
827 }
828
829
830
831
832
833
834
835
836
837
838
839 @Action( ACTION_DO_VALIDATE_FORM )
840 public synchronized XPage doValidateForm( HttpServletRequest request ) throws UserNotSignedException, AccessDeniedException
841 {
842 checkMyLuteceAuthentication( _appointmentForm, request );
843 String strIdForm = request.getParameter( PARAMETER_ID_FORM );
844 if ( _notValidatedAppointment == null || _appointmentForm == null || _notValidatedAppointment.getIdForm( ) != _appointmentForm.getIdForm( ) )
845 {
846
847 addError( ERROR_MESSAGE_FORM_NO_MORE_VALID, getLocale( request ) );
848 _notValidatedAppointment = null;
849 _validatedAppointment = null;
850 return redirectView( request, VIEW_APPOINTMENT_FORM_LIST );
851 }
852 List<GenericAttributeError> listFormErrors = new ArrayList<>( );
853 Locale locale = request.getLocale( );
854 String strEmail = request.getParameter( PARAMETER_EMAIL );
855 String strEmailConfirm = request.getParameter( PARAMETER_EMAIL_CONFIRMATION );
856 String strFirstName = request.getParameter( PARAMETER_FIRST_NAME );
857 String strLastName = request.getParameter( PARAMETER_LAST_NAME );
858 AppointmentUtilities.checkDateOfTheAppointmentIsNotBeforeNow( _notValidatedAppointment, locale, listFormErrors );
859 AppointmentUtilities.checkEmail( strEmail, strEmailConfirm, _appointmentForm, locale, listFormErrors );
860 int nbBookedSeats = _nNbPlacesToTake;
861 if ( _nNbPlacesToTake == 0 )
862 {
863
864 nbBookedSeats = AppointmentUtilities.checkAndReturnNbBookedSeats( request.getParameter( PARAMETER_NUMBER_OF_BOOKED_SEATS ), _appointmentForm,
865 _notValidatedAppointment, locale, listFormErrors );
866
867 }
868 AppointmentUtilities.fillAppointmentDTO( _notValidatedAppointment, nbBookedSeats, strEmail, strEmailConfirm, strFirstName, strLastName );
869 AppointmentUtilities.validateFormAndEntries( _notValidatedAppointment, request, listFormErrors, false );
870 AppointmentUtilities.fillInListResponseWithMapResponse( _notValidatedAppointment );
871 AppointmentUtilities.setAppointmentPhoneNumberValuesFromResponse( _notValidatedAppointment );
872
873 boolean bErrors = false;
874 if ( _appointmentForm.getEnableMandatoryEmail( )
875 && !AppointmentUtilities.checkNbDaysBetweenTwoAppointmentsTaken( _notValidatedAppointment, strEmail, _appointmentForm ) )
876 {
877 addError( ERROR_MESSAGE_NB_MIN_DAYS_BETWEEN_TWO_APPOINTMENTS, locale );
878 bErrors = true;
879 }
880 if ( _appointmentForm.getEnableMandatoryEmail( )
881 && !AppointmentUtilities.checkNbMaxAppointmentsOnAGivenPeriod( _notValidatedAppointment, strEmail, _appointmentForm ) )
882 {
883 addError( ERROR_MESSAGE_NB_MAX_APPOINTMENTS_ON_A_PERIOD, locale );
884 bErrors = true;
885 }
886
887 List<AppointmentDTO> listAppointments = new ArrayList<>( );
888 if ( _appointmentForm.getEnableMandatoryEmail( )
889 && !AppointmentUtilities.checkNbMaxAppointmentsDefinedOnCategory( _notValidatedAppointment, strEmail, _appointmentForm, listAppointments ) )
890 {
891 StringJoiner builder = new StringJoiner( StringUtils.SPACE );
892 String lf = System.getProperty( "line.separator" );
893 for ( AppointmentDTO appt : listAppointments )
894 {
895 builder.add( appt.getLastName( ) );
896 builder.add( appt.getFirstName( ) );
897 builder.add( appt.getDateOfTheAppointment( ) );
898 builder.add( appt.getStartingTime( ).toString( ) );
899 builder.add( lf );
900 }
901 Object [ ] tabAppointment = {
902 builder.toString( )
903 };
904
905 String strErrorMessageDateWithAppointments = I18nService.getLocalizedString( ERROR_MESSAGE_NB_MAX_APPOINTMENTS_ON_A_CATEGORY, tabAppointment,
906 locale );
907 addError( strErrorMessageDateWithAppointments );
908 bErrors = true;
909 }
910 if ( CollectionUtils.isNotEmpty( listFormErrors ) )
911 {
912 getModel( ).put( MARK_FORM_ERRORS, listFormErrors );
913 for ( GenericAttributeError error : listFormErrors )
914 {
915 addError( error.getErrorMessage( ) );
916 }
917 bErrors = true;
918 }
919 if ( bErrors )
920 {
921 LinkedHashMap<String, String> additionalParameters = new LinkedHashMap<>( );
922 additionalParameters.put( PARAMETER_ID_FORM, strIdForm );
923 additionalParameters.put( PARAMETER_MODIFICATION_FORM, String.valueOf( Boolean.TRUE ) );
924 additionalParameters.put( PARAMETER_IS_MODIFICATION, String.valueOf( Boolean.TRUE ) );
925 additionalParameters.put( PARAMETER_ANCHOR, MARK_ANCHOR + STEP_3 );
926 return redirect( request, VIEW_APPOINTMENT_FORM, additionalParameters );
927 }
928 _validatedAppointment = _notValidatedAppointment;
929 _notValidatedAppointment = null;
930 String anchor = request.getParameter( PARAMETER_ANCHOR );
931 if ( StringUtils.isNotEmpty( anchor ) )
932 {
933 Map<String, String> additionalParameters = new HashMap<>( );
934 additionalParameters.put( PARAMETER_ANCHOR, MARK_ANCHOR + anchor );
935
936 return redirect( request, VIEW_DISPLAY_RECAP_APPOINTMENT, additionalParameters );
937 }
938 else
939 {
940 return redirectView( request, VIEW_DISPLAY_RECAP_APPOINTMENT );
941 }
942 }
943
944
945
946
947
948
949
950
951
952
953 @View( VIEW_DISPLAY_RECAP_APPOINTMENT )
954 public synchronized XPage displayRecapAppointment( HttpServletRequest request ) throws UserNotSignedException, AccessDeniedException
955 {
956 checkMyLuteceAuthentication( _appointmentForm, request );
957 String anchor = request.getParameter( PARAMETER_ANCHOR );
958 String strModifDateAppointment = request.getParameter( PARAMETER_MODIF_DATE );
959
960 if ( StringUtils.isNotEmpty( anchor ) )
961 {
962 Map<String, String> additionalParameters = new HashMap<>( );
963 additionalParameters.put( PARAMETER_ANCHOR, MARK_ANCHOR + anchor );
964 return redirect( request, VIEW_DISPLAY_RECAP_APPOINTMENT, additionalParameters );
965 }
966
967 if ( _validatedAppointment == null || _appointmentForm == null || _validatedAppointment.getIdForm( ) != _appointmentForm.getIdForm( ) )
968 {
969 addError( ERROR_MESSAGE_FORM_NO_MORE_VALID, getLocale( request ) );
970 _notValidatedAppointment = null;
971 _validatedAppointment = null;
972 return redirectView( request, VIEW_APPOINTMENT_FORM_LIST );
973 }
974 Map<String, Object> model = new HashMap<>( );
975 if ( _appointmentForm.getEnableCaptcha( ) && getCaptchaService( ).isAvailable( ) )
976 {
977 model.put( MARK_CAPTCHA, getCaptchaService( ).getHtmlCode( ) );
978 }
979 if ( strModifDateAppointment != null && Boolean.parseBoolean( strModifDateAppointment ) )
980 {
981 model.put( MARK_MODIFICATION_DATE_APPOINTMENT, Boolean.TRUE );
982
983 }
984 else
985 {
986
987 model.put( MARK_MODIFICATION_DATE_APPOINTMENT, Boolean.FALSE );
988
989 }
990 model.put( MARK_FORM_MESSAGES, FormMessageService.findFormMessageByIdForm( _validatedAppointment.getIdForm( ) ) );
991 fillCommons( model );
992 model.put( MARK_APPOINTMENT, _validatedAppointment );
993 Locale locale = getLocale( request );
994 model.put( MARK_LIST_RESPONSE_RECAP_DTO, AppointmentUtilities.buildListResponse( _validatedAppointment, request, locale ) );
995 model.put( MARK_FORM, _appointmentForm );
996 model.put( MARK_NBPLACESTOTAKE, _nNbPlacesToTake );
997 model.put( PARAMETER_DATE_OF_DISPLAY, _validatedAppointment.getSlot( ).get( 0 ).getDate( ) );
998
999 return getXPage( TEMPLATE_APPOINTMENT_FORM_RECAP, locale, model );
1000 }
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011 @Action( ACTION_DO_MAKE_APPOINTMENT )
1012 public synchronized XPage doMakeAppointment( HttpServletRequest request ) throws UserNotSignedException, AccessDeniedException
1013 {
1014 checkMyLuteceAuthentication( _appointmentForm, request );
1015 if ( _validatedAppointment == null || _appointmentForm == null || _validatedAppointment.getIdForm( ) != _appointmentForm.getIdForm( ) )
1016 {
1017 addError( ERROR_MESSAGE_FORM_NO_MORE_VALID, getLocale( request ) );
1018 _notValidatedAppointment = null;
1019 _validatedAppointment = null;
1020 return redirectView( request, VIEW_APPOINTMENT_FORM_LIST );
1021 }
1022 if ( !_appointmentForm.getIsActive( ) )
1023 {
1024 addError( ERROR_MESSAGE_FORM_NOT_ACTIVE, getLocale( request ) );
1025 return redirect( request, VIEW_APPOINTMENT_CALENDAR, PARAMETER_ID_FORM, _appointmentForm.getIdForm( ), PARAMETER_NB_PLACE_TO_TAKE,
1026 _nNbPlacesToTake );
1027 }
1028
1029 if ( StringUtils.isNotEmpty( request.getParameter( PARAMETER_BACK ) ) )
1030 {
1031 LinkedHashMap<String, String> parameters = new LinkedHashMap<>( );
1032 parameters.put( PARAMETER_ID_FORM, String.valueOf( _validatedAppointment.getIdForm( ) ) );
1033 parameters.put( PARAMETER_IS_MODIFICATION, String.valueOf( Boolean.TRUE ) );
1034
1035 return redirect( request, VIEW_APPOINTMENT_FORM, parameters );
1036 }
1037 if ( _appointmentForm.getEnableCaptcha( ) && getCaptchaService( ).isAvailable( ) && !getCaptchaService( ).validate( request ) )
1038 {
1039 addError( ERROR_MESSAGE_CAPTCHA, getLocale( request ) );
1040 return redirect( request, VIEW_DISPLAY_RECAP_APPOINTMENT, PARAMETER_ID_FORM, _validatedAppointment.getIdForm( ) );
1041 }
1042
1043 int nIdAppointment;
1044 try
1045 {
1046
1047 nIdAppointment = SlotSafeService.saveAppointment( _validatedAppointment, request );
1048
1049 }
1050 catch( SlotFullException e )
1051 {
1052
1053 addError( ERROR_MESSAGE_SLOT_FULL, getLocale( request ) );
1054 return redirect( request, VIEW_APPOINTMENT_CALENDAR, PARAMETER_ID_FORM, _validatedAppointment.getIdForm( ), PARAMETER_NB_PLACE_TO_TAKE,
1055 _nNbPlacesToTake );
1056 }
1057 catch( SlotEditTaskExpiredTimeException e )
1058 {
1059 addError( ERROR_MESSAGE_SLOT_EDIT_TASK_EXPIRED_TIME, getLocale( request ) );
1060 return redirect( request, VIEW_APPOINTMENT_CALENDAR, PARAMETER_ID_FORM, _validatedAppointment.getIdForm( ), PARAMETER_NB_PLACE_TO_TAKE,
1061 _nNbPlacesToTake );
1062 }
1063 catch( AppointmentSavedException e )
1064 {
1065 nIdAppointment = _validatedAppointment.getIdAppointment( );
1066 AppLogService.error( "Error Save appointment: " + e.getMessage( ), e );
1067 }
1068 AppLogService.info( LogUtilities.buildLog( ACTION_DO_MAKE_APPOINTMENT, Integer.toString( nIdAppointment ), null ) );
1069 AppointmentAsynchronousUploadHandler.getHandler( ).removeSessionFiles( request.getSession( ) );
1070 _nNbPlacesToTake = 0;
1071 int nIdForm = _validatedAppointment.getIdForm( );
1072
1073
1074
1075 AccessControlService.getInstance( ).cleanSessionData( request, nIdForm, Form.RESOURCE_TYPE );
1076
1077 String anchor = request.getParameter( PARAMETER_ANCHOR );
1078 if ( StringUtils.isNotEmpty( anchor ) )
1079 {
1080 LinkedHashMap<String, String> additionalParameters = new LinkedHashMap<>( );
1081 additionalParameters.put( PARAMETER_ID_FORM, String.valueOf( nIdForm ) );
1082 additionalParameters.put( PARAMETER_ANCHOR, MARK_ANCHOR + anchor );
1083 return redirect( request, VIEW_GET_APPOINTMENT_CREATED, additionalParameters );
1084 }
1085 else
1086 {
1087 return redirect( request, VIEW_GET_APPOINTMENT_CREATED, PARAMETER_ID_FORM, nIdForm );
1088 }
1089 }
1090
1091
1092
1093
1094
1095
1096
1097
1098 @View( VIEW_GET_APPOINTMENT_CREATED )
1099 public synchronized XPage getAppointmentCreated( HttpServletRequest request )
1100 {
1101 if( _validatedAppointment == null )
1102 {
1103 return redirectView( request, VIEW_APPOINTMENT_FORM_LIST );
1104 }
1105 int nIdForm = Integer.parseInt( request.getParameter( PARAMETER_ID_FORM ) );
1106 FormMessage formMessages = FormMessageService.findFormMessageByIdForm( nIdForm );
1107 AppointmentFormDTO form = FormService.buildAppointmentForm( nIdForm, 0 );
1108 Slot firstSlot = _validatedAppointment.getSlot().get(0);
1109 Slot lastSlot = firstSlot;
1110 if ( _validatedAppointment.getSlot().size( ) > 1 )
1111 {
1112 lastSlot = _validatedAppointment.getSlot().get(_validatedAppointment.getSlot().size( ) -1 );
1113 }
1114 String strTimeBegin = firstSlot.getStartingDateTime( ).toLocalTime( ).toString( );
1115 String strTimeEnd = lastSlot.getEndingDateTime( ).toLocalTime( ).toString( );
1116 formMessages.setTextAppointmentCreated( formMessages.getTextAppointmentCreated( ).replace( MARK_REF, _validatedAppointment.getReference( ) )
1117 .replace( MARK_DATE_APP, firstSlot.getStartingDateTime().format( Utilities.getFormatter( ) ) )
1118 .replace( MARK_TIME_BEGIN, strTimeBegin ).replace( MARK_TIME_END, strTimeEnd) );
1119 Map<String, Object> model = new HashMap<>( );
1120 model.put( MARK_LIST_RESPONSE_RECAP_DTO, AppointmentUtilities.buildListResponse( _validatedAppointment, request, getLocale( request ) ) );
1121 model.put( MARK_DATE_APPOINTMENT, firstSlot.getDate().format( Utilities.getFormatter( ) ) );
1122 model.put( MARK_STARTING_TIME_APPOINTMENT, firstSlot.getStartingTime( ) );
1123 model.put( MARK_ENDING_TIME_APPOINTMENT, lastSlot.getEndingTime( ) );
1124 model.put( MARK_USER, _validatedAppointment.getUser( ) );
1125 model.put( MARK_PLACES, _validatedAppointment.getNbPlaces( ) );
1126 model.put( MARK_FORM, form );
1127 model.put( MARK_FORM_MESSAGES, formMessages );
1128 _appointmentForm = null;
1129 _validatedAppointment = null;
1130 return getXPage( TEMPLATE_APPOINTMENT_CREATED, getLocale( request ), model );
1131 }
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143 @View( VIEW_CHANGE_DATE_APPOINTMENT )
1144 public synchronized XPage getViewChangeDateAppointment( HttpServletRequest request )
1145 {
1146 String strIdForm = request.getParameter( PARAMETER_ID_FORM );
1147 LocalDateTime startingDateTime = LocalDateTime.parse( request.getParameter( PARAMETER_STARTING_DATE_TIME ) );
1148 Locale locale = getLocale( request );
1149 int nIdForm = Integer.parseInt( strIdForm );
1150 Form form = FormService.findFormLightByPrimaryKey( nIdForm );
1151
1152 if ( !form.getIsActive( ) || _validatedAppointment.getStartingDateTime( ).isBefore( LocalDateTime.now( ) )
1153 || !isAuthorizedDate( startingDateTime, locale ) )
1154 {
1155 _validatedAppointment = null;
1156 addError( ERROR_MESSAGE_FORM_NOT_ACTIVE, getLocale( request ) );
1157 return redirect( request, VIEW_APPOINTMENT_CALENDAR, PARAMETER_ID_FORM, form.getIdForm( ), PARAMETER_NB_PLACE_TO_TAKE, _nNbPlacesToTake );
1158 }
1159 int nNbConsecutiveSlot = ( _nNbPlacesToTake == 0 ) ? 1 : _nNbPlacesToTake;
1160 List<WeekDefinition> listWeekDefinition = WeekDefinitionService.findListWeekDefinition( nIdForm );
1161 Map<WeekDefinition, ReservationRule> mapReservationRule = ReservationRuleService.findAllReservationRule( nIdForm, listWeekDefinition );
1162 List<Slot> listSlot = SlotService.buildListSlot( nIdForm, mapReservationRule, startingDateTime.toLocalDate( ), startingDateTime.toLocalDate( ) );
1163 listSlot = listSlot.stream( )
1164 .filter( s -> ( ( startingDateTime.compareTo( s.getStartingDateTime( ) ) <= 0 ) && ( s.getNbRemainingPlaces( ) > 0 ) && ( s.getIsOpen( ) ) ) )
1165 .limit( nNbConsecutiveSlot ).collect( Collectors.toList( ) );
1166
1167 if ( listSlot == null || ( _nNbPlacesToTake > 0 && listSlot.size( ) != _nNbPlacesToTake ) || !AppointmentUtilities.isConsecutiveSlots( listSlot ) )
1168 {
1169 addError( ERROR_MESSAGE_SLOT_FULL, getLocale( request ) );
1170 return redirect( request, VIEW_APPOINTMENT_CALENDAR, PARAMETER_ID_FORM, nIdForm, PARAMETER_NB_PLACE_TO_TAKE, _nNbPlacesToTake );
1171 }
1172
1173 boolean bool = true;
1174 _validatedAppointment.setSlot( null );
1175 _validatedAppointment.setNbMaxPotentialBookedSeats( 0 );
1176 for ( Slot slot : listSlot )
1177 {
1178
1179 if ( slot.getIdSlot( ) == 0 )
1180 {
1181
1182 slot = SlotSafeService.createSlot( slot );
1183
1184 }
1185 else
1186 {
1187
1188 slot = SlotService.findSlotById( slot.getIdSlot( ) );
1189 }
1190
1191
1192
1193 if ( slot.getNbPotentialRemainingPlaces( ) <= 0 )
1194 {
1195 addError( ERROR_MESSAGE_SLOT_FULL, locale );
1196 return redirect( request, VIEW_APPOINTMENT_CALENDAR, PARAMETER_ID_FORM, nIdForm, PARAMETER_NB_PLACE_TO_TAKE, _nNbPlacesToTake );
1197 }
1198
1199 _validatedAppointment.addSlot( slot );
1200
1201 if ( bool )
1202 {
1203 _validatedAppointment.setDateOfTheAppointment( slot.getDate( ).format( Utilities.getFormatter( ) ) );
1204 ReservationRule reservationRule = ReservationRuleService.findReservationRuleByIdFormAndClosestToDateOfApply( nIdForm, slot.getDate( ) );
1205 _appointmentForm = FormService.buildAppointmentForm( nIdForm, reservationRule );
1206 bool = false;
1207 }
1208 AppointmentUtilities.putTimerInSession( request, slot.getIdSlot( ), _validatedAppointment, _appointmentForm.getMaxPeoplePerAppointment( ) );
1209 }
1210
1211 if ( _validatedAppointment.getNbMaxPotentialBookedSeats( ) == 0 )
1212 {
1213 addError( ERROR_MESSAGE_SLOT_FULL, locale );
1214 return redirect( request, VIEW_APPOINTMENT_CALENDAR, PARAMETER_ID_FORM, nIdForm, PARAMETER_NB_PLACE_TO_TAKE, _nNbPlacesToTake );
1215 }
1216
1217 for ( Response response : _validatedAppointment.getListResponse( ) )
1218 {
1219 if ( response.getFile( ) != null )
1220 {
1221 IFileStoreServiceProvider fileStoreService = FileService.getInstance( ).getFileStoreServiceProvider( );
1222 File file = fileStoreService.getFile( response.getFile( ).getFileKey( ) );
1223 response.setFile( file );
1224 }
1225 }
1226
1227 Map<String, String> additionalParameters = new HashMap<>( );
1228 additionalParameters.put( PARAMETER_MODIF_DATE, "true" );
1229 additionalParameters.put( PARAMETER_ID_FORM, Integer.toString( nIdForm ) );
1230 return redirect( request, VIEW_DISPLAY_RECAP_APPOINTMENT, additionalParameters );
1231 }
1232
1233
1234
1235
1236
1237
1238
1239
1240 @View( value = VIEW_APPOINTMENT_FORM_LIST, defaultView = true )
1241 public synchronized XPage getFormList( HttpServletRequest request )
1242 {
1243 Locale locale = getLocale( request );
1244 _appointmentForm = null;
1245 _validatedAppointment = null;
1246 String strHtmlContent = getFormListHtml( locale, getModel( ) );
1247
1248 XPage xPage = getXPage( );
1249 xPage.setContent( strHtmlContent );
1250 return xPage;
1251 }
1252
1253
1254
1255
1256
1257
1258
1259 @View( VIEW_GET_VIEW_CANCEL_APPOINTMENT )
1260 public synchronized XPage getViewCancelAppointment( HttpServletRequest request )
1261 {
1262 String refAppointment = request.getParameter( PARAMETER_REF_APPOINTMENT );
1263 Appointment appointment = null;
1264 if ( StringUtils.isNotEmpty( refAppointment ) )
1265 {
1266 appointment = AppointmentService.findAppointmentByReference( refAppointment );
1267 }
1268 Map<String, Object> model = new HashMap<>( );
1269 model.put( PARAMETER_REF_APPOINTMENT, refAppointment );
1270 if ( appointment != null )
1271 {
1272
1273 if ( appointment.getIsCancelled( ) )
1274 {
1275 model.put( MARK_APPOINTMENT_ALREADY_CANCELLED, Boolean.TRUE );
1276 }
1277
1278 int nIdAppointment = appointment.getIdAppointment( );
1279 AppointmentDTO appointmentDto = AppointmentService.buildAppointmentDTOFromIdAppointment( nIdAppointment );
1280
1281 if ( appointmentDto.getStartingDateTime( ).isBefore( LocalDateTime.now( ) ) )
1282 {
1283 model.put( MARK_APPOINTMENT_PASSED, Boolean.TRUE );
1284 }
1285 model.put( MARK_DATE_APPOINTMENT, appointmentDto.getDateOfTheAppointment( ) );
1286 model.put( MARK_STARTING_TIME_APPOINTMENT, appointmentDto.getStartingTime( ) );
1287 model.put( MARK_ENDING_TIME_APPOINTMENT, appointmentDto.getEndingTime( ) );
1288 model.put( MARK_PLACES, appointment.getNbPlaces( ) );
1289 model.put( MARK_FORM, FormService.buildAppointmentForm( appointmentDto.getIdForm( ), 0 ) );
1290 model.put( MARK_FORM_MESSAGES, FormMessageService.findFormMessageByIdForm( appointmentDto.getIdForm( ) ) );
1291 AppointmentDTO appointmentDTO = AppointmentService.buildAppointmentDTOFromIdAppointment( nIdAppointment );
1292 appointmentDTO.setListResponse( AppointmentResponseService.findAndBuildListResponse( nIdAppointment, request ) );
1293 appointmentDTO.setMapResponsesByIdEntry( AppointmentResponseService.buildMapFromListResponse( appointmentDTO.getListResponse( ) ) );
1294 model.put( MARK_LIST_RESPONSE_RECAP_DTO, AppointmentUtilities.buildListResponse( appointmentDTO, request, getLocale( request ) ) );
1295 model.put( MARK_USER, UserService.findUserById( appointment.getIdUser( ) ) );
1296
1297 }
1298 else
1299 {
1300 model.put( MARK_NO_APPOINTMENT_WITH_THIS_REFERENCE, Boolean.TRUE );
1301 }
1302 Locale locale = getLocale( request );
1303 XPage xpage = getXPage( TEMPLATE_CANCEL_APPOINTMENT, locale, model );
1304 xpage.setTitle( I18nService.getLocalizedString( MESSAGE_CANCEL_APPOINTMENT_PAGE_TITLE, locale ) );
1305 return xpage;
1306
1307 }
1308
1309
1310
1311
1312
1313
1314
1315 @Action( ACTION_DO_CANCEL_APPOINTMENT )
1316 public synchronized XPage doCancelAppointment( HttpServletRequest request )
1317 {
1318 String strRef = request.getParameter( PARAMETER_REF_APPOINTMENT );
1319 if ( StringUtils.isNotEmpty( strRef ) )
1320 {
1321 Appointment appointment = AppointmentService.findAppointmentByReference( strRef );
1322 AppointmentDTO appointmentDto = AppointmentService.buildAppointmentDTOFromIdAppointment( appointment.getIdAppointment( ) );
1323
1324
1325 if ( !appointment.getIsCancelled( ) && !appointmentDto.getStartingDateTime( ).isBefore( LocalDateTime.now( ) ) )
1326 {
1327
1328 if ( appointment.getIdActionCancelled( ) > 0 )
1329 {
1330 try
1331 {
1332 WorkflowService.getInstance( ).doProcessAction( appointment.getIdAppointment( ), Appointment.APPOINTMENT_RESOURCE_TYPE,
1333 appointment.getIdActionCancelled( ), appointmentDto.getIdForm( ), request, request.getLocale( ), true, null );
1334 AppointmentListenerManager.notifyAppointmentWFActionTriggered( appointment.getIdAppointment( ), appointment.getIdActionCancelled( ) );
1335 }
1336 catch( Exception e )
1337 {
1338 AppLogService.error( "Error Workflow", e );
1339 }
1340 }
1341 else
1342 {
1343 appointment.setIsCancelled( Boolean.TRUE );
1344 AppointmentService.updateAppointment( appointment );
1345 AppLogService.info( LogUtilities.buildLog( ACTION_DO_CANCEL_APPOINTMENT, Integer.toString( appointment.getIdAppointment( ) ), null ) );
1346 }
1347 Map<String, String> mapParameters = new HashMap<>( );
1348 if ( StringUtils.isNotEmpty( request.getParameter( PARAMETER_FROM_MY_APPOINTMENTS ) ) )
1349 {
1350 String strReferer = request.getHeader( PARAMETER_REFERER );
1351 if ( StringUtils.isNotEmpty( strReferer ) )
1352 {
1353 mapParameters.put( MARK_FROM_URL, strReferer );
1354 }
1355 mapParameters.put( PARAMETER_FROM_MY_APPOINTMENTS, request.getParameter( PARAMETER_FROM_MY_APPOINTMENTS ) );
1356 }
1357 mapParameters.put( PARAMETER_ID_FORM, Integer.toString( appointmentDto.getIdForm( ) ) );
1358 return redirect( request, VIEW_APPOINTMENT_CANCELED, mapParameters );
1359 }
1360 }
1361 return redirectView( request, VIEW_APPOINTMENT_FORM_LIST );
1362 }
1363
1364
1365
1366
1367
1368
1369
1370
1371 @View( VIEW_APPOINTMENT_CANCELED )
1372 public synchronized XPage getAppointmentCanceled( HttpServletRequest request )
1373 {
1374 String strIdForm = request.getParameter( PARAMETER_ID_FORM );
1375 if ( StringUtils.isNotEmpty( strIdForm ) && StringUtils.isNumeric( strIdForm ) )
1376 {
1377 int nIdForm = Integer.parseInt( strIdForm );
1378 Map<String, Object> model = new HashMap<>( );
1379 model.put( MARK_FORM_MESSAGES, FormMessageService.findFormMessageByIdForm( nIdForm ) );
1380 if ( Boolean.parseBoolean( request.getParameter( PARAMETER_FROM_MY_APPOINTMENTS ) ) )
1381 {
1382 String strFromUrl = request.getParameter( MARK_FROM_URL );
1383 model.put( MARK_BACK_URL, StringUtils.isNotEmpty( strFromUrl ) ? strFromUrl : getViewUrl( VIEW_GET_MY_APPOINTMENTS ) );
1384 }
1385 return getXPage( TEMPLATE_APPOINTMENT_CANCELED, getLocale( request ), model );
1386 }
1387 return redirectView( request, VIEW_APPOINTMENT_FORM_LIST );
1388 }
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399 @View( VIEW_GET_MY_APPOINTMENTS )
1400 public synchronized XPage getMyAppointments( HttpServletRequest request ) throws UserNotSignedException
1401 {
1402 if ( !SecurityService.isAuthenticationEnable( ) )
1403 {
1404 return redirectView( request, VIEW_APPOINTMENT_FORM_LIST );
1405 }
1406 Locale locale = getLocale( request );
1407 XPage xPage = getXPage( );
1408 xPage.setContent( getMyAppointmentsHtml( request, locale, getModel( ) ) );
1409 xPage.setTitle( I18nService.getLocalizedString( MESSAGE_MY_APPOINTMENTS_PAGE_TITLE, locale ) );
1410 return xPage;
1411 }
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425 @Deprecated
1426 public static String getMyAppointmentsXPage( HttpServletRequest request, Locale locale, Map<String, Object> model ) throws UserNotSignedException
1427 {
1428 if ( !SecurityService.isAuthenticationEnable( ) )
1429 {
1430 return null;
1431 }
1432 LuteceUser luteceUser = SecurityService.getInstance( ).getRegisteredUser( request );
1433 if ( luteceUser == null )
1434 {
1435 throw new UserNotSignedException( );
1436 }
1437 AppointmentFilterDTOointmentFilterDTO.html#AppointmentFilterDTO">AppointmentFilterDTO appointmentFilter = new AppointmentFilterDTO( );
1438 appointmentFilter.setGuid( luteceUser.getName( ) );
1439 List<AppointmentDTO> listAppointmentDTO = AppointmentService.findListAppointmentsDTOByFilter( appointmentFilter );
1440 for ( AppointmentDTO apptDto : listAppointmentDTO )
1441 {
1442 Form form = FormService.findFormLightByPrimaryKey( apptDto.getIdForm( ) );
1443 if ( form.getIdWorkflow( ) > 0 && WorkflowService.getInstance( ).isAvailable( ) )
1444 {
1445
1446 apptDto.setListWorkflowActions( WorkflowService.getInstance( ).getActions( apptDto.getIdAppointment( ), Appointment.APPOINTMENT_RESOURCE_TYPE,
1447 form.getIdWorkflow( ), luteceUser ) );
1448
1449 }
1450 }
1451
1452 model = ( model == null ) ? new HashMap<>( ) : model;
1453 model.put( MARK_LIST_APPOINTMENTS, listAppointmentDTO );
1454 model.put( MARK_FORM_LIST, FormService.findAllInReferenceList( ) );
1455 model.put( MARK_LOCALE_DATE_TIME, LocalDateTime.now( ) );
1456 HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_MY_APPOINTMENTS, locale, model );
1457 return template.getHtml( );
1458 }
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471 public static String getMyAppointmentsHtml( HttpServletRequest request, Locale locale, Map<String, Object> model ) throws UserNotSignedException
1472 {
1473 if ( !SecurityService.isAuthenticationEnable( ) )
1474 {
1475 return null;
1476 }
1477 LuteceUser luteceUser = SecurityService.getInstance( ).getRegisteredUser( request );
1478 if ( luteceUser != null )
1479 {
1480 throw new UserNotSignedException( );
1481 }
1482 AppointmentFilterDTOointmentFilterDTO.html#AppointmentFilterDTO">AppointmentFilterDTO appointmentFilter = new AppointmentFilterDTO( );
1483 appointmentFilter.setGuid( luteceUser.getName( ) );
1484 List<AppointmentDTO> listAppointmentDTO = AppointmentService.findListAppointmentsDTOByFilter( appointmentFilter );
1485 for ( AppointmentDTO apptDto : listAppointmentDTO )
1486 {
1487 Form form = FormService.findFormLightByPrimaryKey( apptDto.getIdForm( ) );
1488 if ( form.getIdWorkflow( ) > 0 && WorkflowService.getInstance( ).isAvailable( ) )
1489 {
1490 apptDto.setListWorkflowActions( WorkflowService.getInstance( ).getActions( apptDto.getIdAppointment( ), Appointment.APPOINTMENT_RESOURCE_TYPE,
1491 form.getIdWorkflow( ), luteceUser ) );
1492 }
1493 }
1494
1495 model = ( model == null ) ? new HashMap<>( ) : model;
1496 model.put( MARK_LIST_APPOINTMENTS, listAppointmentDTO );
1497 model.put( MARK_FORM_LIST, FormService.findAllInReferenceList( ) );
1498 model.put( MARK_LOCALE_DATE_TIME, LocalDateTime.now( ) );
1499 HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_MY_APPOINTMENTS, locale, model );
1500 return template.getHtml( );
1501 }
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514 public static String getFormListHtml( Locale locale, Map<String, Object> model )
1515 {
1516 model = ( model == null ) ? new HashMap<>( ) : model;
1517 List<AppointmentFormDTO> listAppointmentForm = FormService.buildAllActiveAndDisplayedOnPortletAppointmentForm( );
1518
1519 if ( CollectionUtils.isNotEmpty( listAppointmentForm ) )
1520 {
1521 listAppointmentForm = listAppointmentForm.stream( )
1522 .filter( a -> ( a.getDateStartValidity( ) != null ) && ( a.getDateStartValidity( ).toLocalDate( ).isBefore( LocalDate.now( ) )
1523 || a.getDateStartValidity( ).toLocalDate( ).equals( LocalDate.now( ) ) ) )
1524 .sorted( ( a1, a2 ) -> a1.getTitle( ).compareTo( a2.getTitle( ) ) ).collect( Collectors.toList( ) );
1525 }
1526 List<String> icons = new ArrayList<>( );
1527 for ( AppointmentFormDTO form : listAppointmentForm )
1528 {
1529 ImageResource img = form.getIcon( );
1530 if ( img == null || img.getImage( ) == null || StringUtils.isEmpty( img.getMimeType( ) )
1531 || StringUtils.equals( img.getMimeType( ), MARK_ICON_NULL ) )
1532 {
1533 icons.add( MARK_ICON_NULL );
1534 }
1535 else
1536 {
1537 byte [ ] imgBytesAsBase64 = Base64.encodeBase64( img.getImage( ) );
1538 String imgDataAsBase64 = new String( imgBytesAsBase64 );
1539 String strMimeType = img.getMimeType( );
1540 String imgAsBase64 = MARK_DATA + MARK_COLON + strMimeType + MARK_SEMI_COLON + MARK_BASE_64 + MARK_COMMA + imgDataAsBase64;
1541 icons.add( imgAsBase64 );
1542 }
1543 }
1544 model.put( MARK_ICONS, icons );
1545 model.put( MARK_FORM_LIST, listAppointmentForm );
1546 HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_APPOINTMENT_FORM_LIST, locale, model );
1547 return template.getHtml( );
1548 }
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558 @View( VIEW_WORKFLOW_ACTION_FORM )
1559 public synchronized XPage getWorkflowActionForm( HttpServletRequest request ) throws UserNotSignedException
1560 {
1561 String strIdAction = request.getParameter( PARAMETER_ID_ACTION );
1562 String refAppointment = request.getParameter( PARAMETER_REF_APPOINTMENT );
1563 if ( StringUtils.isNotEmpty( strIdAction ) && StringUtils.isNumeric( strIdAction ) && StringUtils.isNotEmpty( refAppointment ) )
1564 {
1565 int nIdAction = Integer.parseInt( strIdAction );
1566 if ( WorkflowService.getInstance( ).isDisplayTasksForm( nIdAction, getLocale( request ) ) )
1567 {
1568 AppointmentDTO appointment = AppointmentService.buildAppointmentDTOFromRefAppointment( refAppointment );
1569
1570 if( appointment == null )
1571 {
1572
1573 return getXPage( TEMPLATE_ERROR_APPOINTMENT_REFERENCE, getLocale( request ), null );
1574 }
1575 ITaskService taskService = SpringContextService.getBean( TaskService.BEAN_SERVICE );
1576 List<ITask> listActionTasks = taskService.getListTaskByIdAction( nIdAction, getLocale( request ) );
1577 if ( listActionTasks.stream( ).anyMatch( task -> task.getTaskType( ).getKey( ).equals( "taskReportAppointment" ) ) )
1578 {
1579 Map<String, String> additionalParameters = new HashMap<>( );
1580 additionalParameters.put( PARAMETER_REF_APPOINTMENT, appointment.getReference( ) );
1581 additionalParameters.put( PARAMETER_NB_PLACE_TO_TAKE, String.valueOf( appointment.getNbBookedSeats( ) ) );
1582 additionalParameters.put( PARAMETER_ID_FORM, String.valueOf( appointment.getIdForm( ) ) );
1583 return redirect( request, VIEW_APPOINTMENT_CALENDAR, additionalParameters );
1584 }
1585 String strHtmlTasksForm = WorkflowService.getInstance( ).getDisplayTasksForm( appointment.getIdAppointment( ),
1586 Appointment.APPOINTMENT_RESOURCE_TYPE, nIdAction, request, getLocale( request ), null );
1587 Map<String, Object> model = getModel( );
1588 model.put( MARK_TASKS_FORM, strHtmlTasksForm );
1589 model.put( PARAMETER_ID_ACTION, nIdAction );
1590 model.put( PARAMETER_REF_APPOINTMENT, refAppointment );
1591
1592 return getXPage( TEMPLATE_TASKS_FORM_WORKFLOW, getLocale( request ), model );
1593 }
1594
1595 return doProcessWorkflowAction( request );
1596 }
1597 return getMyAppointments( request );
1598 }
1599
1600
1601
1602
1603
1604
1605
1606
1607 @Action( ACTION_DO_PROCESS_WORKFLOW_ACTION )
1608 public synchronized XPage doProcessWorkflowAction( HttpServletRequest request ) throws UserNotSignedException
1609 {
1610 LuteceUser luteceUser = SecurityService.getInstance( ).getRegisteredUser( request );
1611 String strIdAction = request.getParameter( PARAMETER_ID_ACTION );
1612 String refAppointment = request.getParameter( PARAMETER_REF_APPOINTMENT );
1613 if ( StringUtils.isNotEmpty( strIdAction ) && StringUtils.isNumeric( strIdAction ) && StringUtils.isNotEmpty( refAppointment ) )
1614 {
1615 int nIdAction = Integer.parseInt( strIdAction );
1616 Appointment appointment = AppointmentService.findAppointmentByReference( refAppointment );
1617
1618 if( appointment == null )
1619 {
1620
1621 return getXPage( TEMPLATE_ERROR_APPOINTMENT_REFERENCE, getLocale( request ), null );
1622 }
1623 int nIdAppointment = appointment.getIdAppointment( );
1624
1625 List<AppointmentSlot> listApptSlot = appointment.getListAppointmentSlot( );
1626 Slot slot = SlotService.findSlotById( listApptSlot.get( 0 ).getIdSlot( ) );
1627
1628 if ( request.getParameter( PARAMETER_BACK ) == null )
1629 {
1630 try
1631 {
1632 if ( WorkflowService.getInstance( ).isDisplayTasksForm( nIdAction, getLocale( request ) ) )
1633 {
1634 if ( WorkflowService.getInstance( ).canProcessAction( nIdAppointment, Appointment.APPOINTMENT_RESOURCE_TYPE, nIdAction,
1635 slot.getIdForm( ), request, false, luteceUser ) )
1636 {
1637
1638 String strError = WorkflowService.getInstance( ).doSaveTasksForm( nIdAppointment, Appointment.APPOINTMENT_RESOURCE_TYPE, nIdAction,
1639 slot.getIdForm( ), request, getLocale( request ), luteceUser );
1640 if ( strError != null )
1641 {
1642 AppLogService.error( "Error Workflow:" + strError );
1643 addError( strError );
1644 return getWorkflowActionForm( request );
1645 }
1646 }
1647 else
1648 {
1649
1650 AppLogService.error( "Error Workflow can not process Action" );
1651 addError( "Error Workflow can not process Action" );
1652 return getMyAppointments( request );
1653 }
1654 }
1655 else
1656 {
1657 ITaskService taskService = SpringContextService.getBean( TaskService.BEAN_SERVICE );
1658 List<ITask> listActionTasks = taskService.getListTaskByIdAction( nIdAction, getLocale( request ) );
1659 for ( ITask task : listActionTasks )
1660 {
1661 if ( task.getTaskType( ).getKey( ).equals( "taskChangeAppointmentStatus" ) && ( appointment.getIsCancelled( ) ) )
1662 {
1663 for ( AppointmentSlot apptSlt : listApptSlot )
1664 {
1665
1666 Slot slt = SlotService.findSlotById( apptSlt.getIdSlot( ) );
1667
1668 if ( apptSlt.getNbPlaces( ) > slt.getNbRemainingPlaces( ) )
1669 {
1670 AppLogService.error( "Error Workflow:" + ERROR_MESSAGE_SLOT_FULL );
1671 addError( ERROR_MESSAGE_SLOT_FULL, getLocale( request ) );
1672 return getMyAppointments( request );
1673
1674 }
1675 }
1676 }
1677 }
1678
1679 WorkflowService.getInstance( ).doProcessAction( nIdAppointment, Appointment.APPOINTMENT_RESOURCE_TYPE, nIdAction, slot.getIdForm( ),
1680 request, getLocale( request ), false, luteceUser );
1681 AppointmentListenerManager.notifyAppointmentWFActionTriggered( nIdAppointment, nIdAction );
1682
1683 }
1684 addInfo( MESSAGE_WF_ACTION_SUCESS, getLocale( request ) );
1685 }
1686 catch( Exception e )
1687 {
1688 AppLogService.error( "Error Workflow", e );
1689 }
1690
1691 }
1692 }
1693 return getMyAppointments( request );
1694 }
1695
1696
1697
1698
1699
1700
1701 private CaptchaSecurityService getCaptchaService( )
1702 {
1703 if ( _captchaSecurityService == null )
1704 {
1705 _captchaSecurityService = new CaptchaSecurityService( );
1706 }
1707
1708 return _captchaSecurityService;
1709 }
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720 public static String getCancelAppointmentUrl( HttpServletRequest request, Appointment appointment )
1721 {
1722 UrlItem urlItem = new UrlItem( AppPathService.getProdUrl( request ) + AppPathService.getPortalUrl( ) );
1723 urlItem.addParameter( MVCUtils.PARAMETER_PAGE, XPAGE_NAME );
1724 urlItem.addParameter( MVCUtils.PARAMETER_VIEW, VIEW_GET_VIEW_CANCEL_APPOINTMENT );
1725 urlItem.addParameter( PARAMETER_REF_APPOINTMENT, appointment.getReference( ) );
1726 return urlItem.getUrl( );
1727 }
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738 public static String getCancelAppointmentUrl( Appointment appointment )
1739 {
1740 UrlItem urlItem = new UrlItem( AppPathService.getProdUrl( StringUtils.EMPTY ) + AppPathService.getPortalUrl( ) );
1741 urlItem.addParameter( MVCUtils.PARAMETER_PAGE, XPAGE_NAME );
1742 urlItem.addParameter( MVCUtils.PARAMETER_VIEW, VIEW_GET_VIEW_CANCEL_APPOINTMENT );
1743 urlItem.addParameter( PARAMETER_REF_APPOINTMENT, appointment.getReference( ) );
1744 return urlItem.getUrl( );
1745 }
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756 public static String getReportAppointmentUrl( AppointmentDTO appointment )
1757 {
1758 UrlItem urlItem = new UrlItem( AppPathService.getProdUrl( StringUtils.EMPTY ) + AppPathService.getPortalUrl( ) );
1759 urlItem.addParameter( MVCUtils.PARAMETER_PAGE, XPAGE_NAME );
1760 urlItem.addParameter( MVCUtils.PARAMETER_VIEW, VIEW_APPOINTMENT_CALENDAR );
1761 urlItem.addParameter( PARAMETER_ID_FORM, appointment.getIdForm( ) );
1762 urlItem.addParameter( PARAMETER_NB_PLACE_TO_TAKE, appointment.getNbBookedSeats( ) );
1763 urlItem.addParameter( PARAMETER_REF_APPOINTMENT, appointment.getReference( ) );
1764 return urlItem.getUrl( );
1765 }
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775 public void setUserInfo( HttpServletRequest request, AppointmentDTO appointment )
1776 {
1777 if ( SecurityService.isAuthenticationEnable( ) && ( appointment != null ) )
1778 {
1779 LuteceUser user = SecurityService.getInstance( ).getRegisteredUser( request );
1780
1781 if ( user != null )
1782 {
1783 appointment.setGuid( user.getName( ) );
1784 appointment.setFirstName( user.getUserInfo( AppPropertiesService.getProperty( PROPERTY_USER_ATTRIBUTE_FIRST_NAME, StringUtils.EMPTY ) ) );
1785 appointment.setEmail( user.getUserInfo( AppPropertiesService.getProperty( PROPERTY_USER_ATTRIBUTE_EMAIL, StringUtils.EMPTY ) ) );
1786 String lastName = user.getUserInfo( AppPropertiesService.getProperty( PROPERTY_USER_ATTRIBUTE_PREFERED_NAME, StringUtils.EMPTY ) );
1787 if ( ( lastName == null ) || lastName.isEmpty( ) )
1788 {
1789 lastName = user.getUserInfo( AppPropertiesService.getProperty( PROPERTY_USER_ATTRIBUTE_LAST_NAME, StringUtils.EMPTY ) );
1790 }
1791 appointment.setLastName( lastName );
1792 }
1793 }
1794 }
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806 private void checkMyLuteceAuthentication( AppointmentFormDTO form, HttpServletRequest request ) throws UserNotSignedException, AccessDeniedException
1807 {
1808 if ( !SecurityService.isAuthenticationEnable( ) )
1809 {
1810 return;
1811 }
1812
1813
1814 SecurityService securityService = SecurityService.getInstance( );
1815 if ( securityService.isExternalAuthentication( ) )
1816 {
1817 if ( form.getActiveAuthentication( ) )
1818 {
1819
1820
1821 if ( securityService.getRegisteredUser( request ) == null && securityService.getRemoteUser( request ) == null )
1822 {
1823
1824 throw new UserNotSignedException( );
1825 }
1826
1827 if ( !Form.ROLE_NONE.equals( form.getRole( ) ) && !securityService.isUserInRole( request, form.getRole( ) ) )
1828 {
1829
1830 throw new AccessDeniedException( "Unauthorized" );
1831 }
1832 }
1833 }
1834 else
1835 {
1836
1837
1838
1839 if ( form.getActiveAuthentication( ) && securityService.getRegisteredUser( request ) == null && !securityService.isLoginUrl( request ) )
1840 {
1841
1842 throw new UserNotSignedException( );
1843 }
1844 }
1845 }
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856 private boolean isAuthorizedDate( LocalDateTime date, Locale locale )
1857 {
1858
1859 LocalDateTime startingDateOfDisplay = LocalDateTime.now( ).plusHours( _appointmentForm.getMinTimeBeforeAppointment( ) );
1860
1861 LocalDateTime startingValidityDate = _appointmentForm.getDateStartValidity( ).toLocalDate( ).atStartOfDay( );
1862 if ( startingValidityDate.isAfter( startingDateOfDisplay ) )
1863 {
1864 startingDateOfDisplay = startingValidityDate;
1865 }
1866
1867
1868 LocalDate endingDateOfDisplay = startingDateOfDisplay.toLocalDate( ).with( WeekFields.of( locale ).dayOfWeek( ), DayOfWeek.SUNDAY.getValue( ) )
1869 .plusWeeks( (long) _appointmentForm.getNbWeeksToDisplay( ) - 1 );
1870 return !( date.toLocalDate( ).isAfter( endingDateOfDisplay ) || date.isBefore( startingDateOfDisplay ) );
1871
1872 }
1873 }