AppointmentJspBean.java
/*
* Copyright (c) 2002-2022, City of Paris
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright notice
* and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice
* and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* License 1.0
*/
package fr.paris.lutece.plugins.appointment.web;
import java.io.IOException;
import java.io.OutputStream;
import java.sql.Date;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.StringJoiner;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import fr.paris.lutece.portal.service.file.FileService;
import fr.paris.lutece.portal.service.file.FileServiceException;
import fr.paris.lutece.portal.service.file.IFileStoreServiceProvider;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import fr.paris.lutece.api.user.User;
import fr.paris.lutece.plugins.appointment.business.appointment.Appointment;
import fr.paris.lutece.plugins.appointment.business.appointment.AppointmentSlot;
import fr.paris.lutece.plugins.appointment.business.form.Form;
import fr.paris.lutece.plugins.appointment.business.message.FormMessage;
import fr.paris.lutece.plugins.appointment.business.planning.WeekDefinition;
import fr.paris.lutece.plugins.appointment.business.rule.FormRule;
import fr.paris.lutece.plugins.appointment.business.rule.ReservationRule;
import fr.paris.lutece.plugins.appointment.business.slot.Slot;
import fr.paris.lutece.plugins.appointment.exception.AppointmentSavedException;
import fr.paris.lutece.plugins.appointment.exception.SlotEditTaskExpiredTimeException;
import fr.paris.lutece.plugins.appointment.exception.SlotFullException;
import fr.paris.lutece.plugins.appointment.log.LogUtilities;
import fr.paris.lutece.plugins.appointment.service.AppointmentResourceIdService;
import fr.paris.lutece.plugins.appointment.service.AppointmentResponseService;
import fr.paris.lutece.plugins.appointment.service.AppointmentService;
import fr.paris.lutece.plugins.appointment.service.AppointmentUtilities;
import fr.paris.lutece.plugins.appointment.service.CommentService;
import fr.paris.lutece.plugins.appointment.service.EntryService;
import fr.paris.lutece.plugins.appointment.service.FormMessageService;
import fr.paris.lutece.plugins.appointment.service.FormRuleService;
import fr.paris.lutece.plugins.appointment.service.FormService;
import fr.paris.lutece.plugins.appointment.service.ReservationRuleService;
import fr.paris.lutece.plugins.appointment.service.SlotSafeService;
import fr.paris.lutece.plugins.appointment.service.SlotService;
import fr.paris.lutece.plugins.appointment.service.Utilities;
import fr.paris.lutece.plugins.appointment.service.WeekDefinitionService;
import fr.paris.lutece.plugins.appointment.service.addon.AppointmentAddOnManager;
import fr.paris.lutece.plugins.appointment.service.export.AppointmentExportService;
import fr.paris.lutece.plugins.appointment.service.export.ExcelAppointmentGenerator;
import fr.paris.lutece.plugins.appointment.service.listeners.AppointmentListenerManager;
import fr.paris.lutece.plugins.appointment.service.upload.AppointmentAsynchronousUploadHandler;
import fr.paris.lutece.plugins.appointment.web.dto.AppointmentDTO;
import fr.paris.lutece.plugins.appointment.web.dto.AppointmentFilterDTO;
import fr.paris.lutece.plugins.appointment.web.dto.AppointmentFormDTO;
import fr.paris.lutece.plugins.filegenerator.service.TemporaryFileGeneratorService;
import fr.paris.lutece.plugins.genericattributes.business.Entry;
import fr.paris.lutece.plugins.genericattributes.business.EntryHome;
import fr.paris.lutece.plugins.genericattributes.business.GenericAttributeError;
import fr.paris.lutece.plugins.genericattributes.business.Response;
import fr.paris.lutece.plugins.genericattributes.business.ResponseHome;
import fr.paris.lutece.plugins.workflowcore.business.state.State;
import fr.paris.lutece.plugins.workflowcore.business.state.StateFilter;
import fr.paris.lutece.plugins.workflowcore.service.state.StateService;
import fr.paris.lutece.plugins.workflowcore.service.task.ITask;
import fr.paris.lutece.plugins.workflowcore.service.task.ITaskService;
import fr.paris.lutece.plugins.workflowcore.service.task.TaskService;
import fr.paris.lutece.portal.business.file.File;
import fr.paris.lutece.portal.business.user.AdminUser;
import fr.paris.lutece.portal.business.user.AdminUserHome;
import fr.paris.lutece.portal.service.admin.AccessDeniedException;
import fr.paris.lutece.portal.service.admin.AdminAuthenticationService;
import fr.paris.lutece.portal.service.i18n.I18nService;
import fr.paris.lutece.portal.service.mailinglist.AdminMailingListService;
import fr.paris.lutece.portal.service.message.AdminMessage;
import fr.paris.lutece.portal.service.message.AdminMessageService;
import fr.paris.lutece.portal.service.plugin.Plugin;
import fr.paris.lutece.portal.service.plugin.PluginService;
import fr.paris.lutece.portal.service.rbac.RBACService;
import fr.paris.lutece.portal.service.spring.SpringContextService;
import fr.paris.lutece.portal.service.template.AppTemplateService;
import fr.paris.lutece.portal.service.util.AppLogService;
import fr.paris.lutece.portal.service.util.AppPathService;
import fr.paris.lutece.portal.service.util.AppPropertiesService;
import fr.paris.lutece.portal.service.workflow.WorkflowService;
import fr.paris.lutece.portal.util.mvc.admin.MVCAdminJspBean;
import fr.paris.lutece.portal.util.mvc.admin.annotations.Controller;
import fr.paris.lutece.portal.util.mvc.commons.annotations.Action;
import fr.paris.lutece.portal.util.mvc.commons.annotations.View;
import fr.paris.lutece.portal.util.mvc.utils.MVCUtils;
import fr.paris.lutece.portal.web.util.LocalizedPaginator;
import fr.paris.lutece.util.ReferenceList;
import fr.paris.lutece.util.html.AbstractPaginator;
import fr.paris.lutece.util.html.HtmlTemplate;
import fr.paris.lutece.util.url.UrlItem;
/**
* This class provides the user interface to manage Appointment features ( manage, create, modify, remove )
*
* @author Laurent Payen
*
*/
@Controller( controllerJsp = "ManageAppointments.jsp", controllerPath = "jsp/admin/plugins/appointment/", right = AppointmentFormJspBean.RIGHT_MANAGEAPPOINTMENTFORM )
public class AppointmentJspBean extends MVCAdminJspBean
{
/**
* Serial version UID
*/
private static final long serialVersionUID = 1978001810468444844L;
private static final String PARAMETER_PAGE_INDEX = "page_index";
// //////////////////////////////////////////////////////////////////////////
// Constants
// templates
private static final String TEMPLATE_MANAGE_APPOINTMENTS_CALENDAR = "/admin/plugins/appointment/appointment/manage_appointments_calendar.html";
private static final String TEMPLATE_MANAGE_APPOINTMENTS_CALENDAR_MULTI_SLOT = "/admin/plugins/appointment/appointment/manage_appointments_multislot_calendar.html";
private static final String TEMPLATE_MANAGE_APPOINTMENTS_CALENDAR_GROUPED = "/admin/plugins/appointment/appointment/appointment_form_list_open_slots_grouped.html";
private static final String TEMPLATE_CREATE_APPOINTMENT = "/admin/plugins/appointment/appointment/create_appointment.html";
private static final String TEMPLATE_MANAGE_APPOINTMENTS = "/admin/plugins/appointment/appointment/manage_appointments.html";
private static final String TEMPLATE_VIEW_APPOINTMENT = "/admin/plugins/appointment/appointment/view_appointment.html";
private static final String TEMPLATE_HTML_CODE_FORM_ADMIN = "admin/plugins/appointment/html_code_form.html";
private static final String TEMPLATE_APPOINTMENT_FORM_RECAP = "/admin/plugins/appointment/appointment/appointment_form_recap.html";
private static final String TEMPLATE_TASKS_FORM_WORKFLOW = "admin/plugins/appointment/appointment/tasks_form_workflow.html";
// Properties for page titles
private static final String PROPERTY_PAGE_TITLE_MANAGE_APPOINTMENTS = "appointment.manageAppointments.pageTitle";
private static final String PROPERTY_PAGE_TITLE_MANAGE_APPOINTMENTS_CALENDAR = "appointment.manageAppointmentCalendar.pageTitle";
private static final String PROPERTY_PAGE_TITLE_CREATE_APPOINTMENT = "appointment.name.create";
private static final String PROPERTY_PAGE_TITLE_VIEW_APPOINTMENT = "appointment.viewAppointment.pageTitle";
private static final String PROPERTY_PAGE_TITLE_RECAP_APPOINTMENT = "appointment.appointmentApp.recap.title";
private static final String PROPERTY_PAGE_TITLE_TASKS_FORM_WORKFLOW = "appointment.taskFormWorkflow.pageTitle";
private static final String UNRESERVED = "appointment.message.labelStatusUnreserved";
private static final String RESERVED = "appointment.message.labelStatusReserved";
// Parameters
private static final String PARAMETER_ID_RESPONSE = "idResponse";
private static final String PARAMETER_STARTING_DATE_TIME = "starting_date_time";
private static final String PARAMETER_ENDING_DATE_TIME = "ending_date_time";
private static final String PARAMETER_STARTING_DATE_OF_DISPLAY = "starting_date_of_display";
private static final String PARAMETER_STR_STARTING_DATE_OF_DISPLAY = "str_starting_date_of_display";
private static final String PARAMETER_ENDING_DATE_OF_DISPLAY = "ending_date_of_display";
private static final String PARAMETER_STR_ENDING_DATE_OF_DISPLAY = "str_ending_date_of_display";
private static final String PARAMETER_DATE_OF_DISPLAY = "date_of_display";
private static final String PARAMETER_DAY_OF_WEEK = "dow";
private static final String PARAMETER_EVENTS = "events";
private static final String PARAMETER_EVENTS_COMMENTS = "comment_events";
private static final String PARAMETER_MIN_DURATION = "min_duration";
private static final String PARAMETER_MIN_TIME = "min_time";
private static final String PARAMETER_MAX_TIME = "max_time";
private static final String PARAMETER_ID_APPOINTMENT = "id_appointment";
private static final String PARAMETER_ID_ACTION = "id_action";
private static final String PARAMETER_ID_FORM = "id_form";
private static final String PARAMETER_COME_FROM_CALENDAR = "comeFromCalendar";
private static final String PARAMETER_EMAIL = "email";
private static final String PARAMETER_EMAIL_CONFIRMATION = "emailConfirm";
private static final String PARAMETER_FIRST_NAME = "firstname";
private static final String PARAMETER_LAST_NAME = "lastname";
private static final String PARAMETER_BACK = "back";
private static final String PARAMETER_ORDER_BY = "orderBy";
private static final String PARAMETER_ORDER_ASC = "orderAsc";
private static final String PARAMETER_ID_APPOINTMENT_DELETE = "apmt";
private static final String PARAMETER_DELETE_AND_BACK = "eraseAll";
private static final String PARAMETER_SEARCH = "Search";
private static final String PARAMETER_RESET = "reset";
private static final String PARAMETER_NUMBER_OF_BOOKED_SEATS = "nbBookedSeats";
private static final String PARAMETER_STATUS_CANCELLED = "status_cancelled";
private static final String PARAMETER_MODIF_DATE = "modif_date";
private static final String PARAMETER_IS_MODIFICATION = "is_modification";
private static final String PARAMETER_NB_PLACE_TO_TAKE = "nbPlacesToTake";
private static final String PARAMETER_SELECTED_DEFAULT_FIELD = "selectedDefaultFieldList";
private static final String PARAMETER_SELECTED_CUSTOM_FIELD = "selectedCustomFieldList";
// Markers
private static final String MARK_TASKS_FORM = "tasks_form";
private static final String MARK_APPOINTMENT_LIST = "appointment_list";
private static final String MARK_APPOINTMENT = "appointment";
private static final String MARK_PAGINATOR = "paginator";
private static final String MARK_NB_ITEMS_PER_PAGE = "nb_items_per_page";
private static final String MARK_FORM_MESSAGES = "formMessages";
private static final String MARK_FORM_HTML = "form_html";
private static final String MARK_FORM = "form";
private static final String MARK_MODIFICATION_DATE_APPOINTMENT = "modifDateAppointment";
private static final String MARK_FORM_CALENDAR_ERRORS = "formCalendarErrors";
private static final String MARK_FORM_ERRORS = "form_errors";
private static final String MARK_LIST_ERRORS = "listAllErrors";
private static final String MARK_LOCALE = "locale";
private static final String MARK_PLACES = "nbplaces";
private static final String MARK_STR_ENTRY = "str_entry";
private static final String MARK_RIGHT_CREATE = "rightCreate";
private static final String MARK_RIGHT_DELETE = "rightDelete";
private static final String MARK_RIGHT_VIEW = "rightView";
private static final String MARK_RIGHT_CHANGE_STATUS = "rightChangeStatus";
private static final String MARK_FILTER = "filter";
private static final String MARK_LIST_STATUS = "listStatus";
private static final String MARK_RESOURCE_HISTORY = "resource_history";
private static final String MARK_ADDON = "addon";
private static final String MARK_LIST_RESPONSE_RECAP_DTO = "listResponseRecapDTO";
private static final String MARK_LANGUAGE = "language";
private static final String MARK_ACTIVATE_WORKFLOW = "activateWorkflow";
private static final String MARK_FORM_OVERBOOKING_ALLOWED = "overbookingAllowed";
private static final String MARK_DEFAULT_FIELD_LIST = "defaultFieldList";
private static final String MARK_CUSTOM_FIELD_LIST = "customFieldList";
private static final String MARK_IS_OVERBOOKING = "isOverbooking";
private static final String MARK_MAILING_LIST = "mailing_list";
private static final String MARK_USER_CREATOR = "userCreator";
private static final String JSP_MANAGE_APPOINTMENTS = "jsp/admin/plugins/appointment/ManageAppointments.jsp";
private static final String ERROR_MESSAGE_SLOT_FULL = "appointment.message.error.slotFull";
private static final String ERROR_MESSAGE_SLOT_EDIT_TASK_EXPIRED_TIME = "appointment.message.error.appointment.edit.expired.time";
private static final String MARK_APPOINTMENT_DESK_ENABLED = "isDeskInstalled";
// Messages
private static final String MESSAGE_CONFIRM_REMOVE_APPOINTMENT = "appointment.message.confirmRemoveAppointment";
private static final String MESSAGE_CONFIRM_REMOVE_MASSAPPOINTMENT = "appointment.message.confirmRemoveMassAppointment";
private static final String ERROR_MESSAGE_NB_MAX_APPOINTMENTS_ON_A_CATEGORY = "appointment.validation.appointment.NbMaxAppointmentsOnCategory.error";
private static final String ERROR_MESSAGE_NB_MIN_DAYS_BETWEEN_TWO_APPOINTMENTS = "appointment.validation.appointment.NbMinDaysBetweenTwoAppointments.error";
private static final String ERROR_MESSAGE_NB_MAX_APPOINTMENTS_ON_A_PERIOD = "appointment.validation.appointment.NbMaxAppointmentsOnAPeriod.error";
// Properties
private static final String PROPERTY_DEFAULT_LIST_APPOINTMENT_PER_PAGE = "appointment.listAppointments.itemsPerPage";
private static final String PROPERTY_NB_WEEKS_TO_DISPLAY_IN_BO = "appointment.nbWeeksToDisplayInBO";
private static final String PROPERTY_MODULE_APPOINTMENT_DESK_NAME = "appointment.moduleAppointmentDesk.name";
// Views
private static final String VIEW_MANAGE_APPOINTMENTS = "manageAppointments";
private static final String VIEW_CREATE_APPOINTMENT = "createAppointment";
private static final String VIEW_VIEW_APPOINTMENT = "viewAppointment";
private static final String VIEW_DISPLAY_RECAP_APPOINTMENT = "displayRecapAppointment";
private static final String VIEW_CALENDAR_MANAGE_APPOINTMENTS = "viewCalendarManageAppointment";
private static final String VIEW_WORKFLOW_ACTION_FORM = "viewWorkflowActionForm";
private static final String VIEW_CHANGE_DATE_APPOINTMENT = "viewChangeDateAppointment";
// Actions
private static final String ACTION_DO_VALIDATE_FORM = "doValidateForm";
private static final String ACTION_REMOVE_APPOINTMENT = "removeAppointment";
private static final String ACTION_REMOVE_MASSAPPOINTMENT = "removeMassAppointment";
private static final String ACTION_CONFIRM_REMOVE_APPOINTMENT = "confirmRemoveAppointment";
private static final String ACTION_CONFIRM_REMOVE_MASS_APPOINTMENT = "confirmRemoveMassAppointment";
private static final String ACTION_DO_MAKE_APPOINTMENT = "doMakeAppointment";
private static final String ACTION_DO_PROCESS_WORKFLOW_ACTION = "doProcessWorkflowAction";
private static final String ACTION_DO_CHANGE_APPOINTMENT_STATUS = "doChangeAppointmentStatus";
private static final String ACTION_EXPORT_APPOINTMENTS = "doExportAppointments";
// Infos
private static final String INFO_APPOINTMENT_CREATED = "appointment.info.appointment.created";
private static final String INFO_APPOINTMENT_REMOVED = "appointment.info.appointment.removed";
private static final String INFO_APPOINTMENT_MASSREMOVED = "appointment.info.appointment.removed";
// Error
private static final String ERROR_MESSAGE_FORM_NOT_ACTIVE = "appointment.validation.appointment.formNotActive";
private static final String ERROR_MESSAGE_NO_STARTING_VALIDITY_DATE = "appointment.validation.appointment.noStartingValidityDate";
private static final String ERROR_MESSAGE_FORM_NO_MORE_VALID = "appointment.validation.appointment.formNoMoreValid";
private static final String MESSAGE_UNVAILABLE_SLOT = "appointment.slot.unvailable";
private static final String ERROR_MESSAGE_REPORT_APPOINTMENT = "appointment.message.error.report.appointment";
// Constants
private static final String DEFAULT_CURRENT_PAGE = "1";
public static final String ACTIVATEWORKFLOW = AppPropertiesService.getProperty( "appointment.activate.workflow" );
public static final String PREVIOUS_FORM = "calendar";
private static final String LAST_NAME = "last_name";
private static final String FIRST_NAME = "first_name";
private static final String EMAIL = "email";
private static final String PHONE_NUMBER = "phone_number";
private static final String NB_BOOKED_SEATS = "nbBookedSeats";
private static final String DATE_APPOINTMENT = "date_appointment";
private static final String ADMIN = "admin";
private static final String STATUS = "status";
// services
// Session variable to store working values
private String _strCurrentPageIndex;
private int _nItemsPerPage;
private int _nDefaultItemsPerPage;
private int _nNbPlacesToTake;
private AppointmentFilterDTO _filter;
private AppointmentFormDTO _appointmentForm;
private AppointmentDTO _notValidatedAppointment;
private AppointmentDTO _validatedAppointment;
private List<Integer> _listAppointmentsIds;
List<GenericAttributeError> listFormErrors = new ArrayList<>( );
Plugin _moduleAppointmentDesk = PluginService.getPlugin( AppPropertiesService.getProperty( PROPERTY_MODULE_APPOINTMENT_DESK_NAME ) );
/**
* Get the page to manage appointments. Appointments are displayed in a calendar.
*
* @param request
* The request
* @return The HTML code to display
* @throws AccessDeniedException
*/
@View( value = VIEW_CALENDAR_MANAGE_APPOINTMENTS, defaultView = true )
public synchronized String getViewCalendarManageAppointments( HttpServletRequest request ) throws AccessDeniedException
{
String strIdForm = request.getParameter( PARAMETER_ID_FORM );
if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm, AppointmentResourceIdService.PERMISSION_VIEW_FORM, (User) getUser( ) ) )
{
throw new AccessDeniedException( AppointmentResourceIdService.PERMISSION_VIEW_FORM );
}
cleanSession( request.getSession( ) );
String strIdAppointment = request.getParameter( PARAMETER_ID_APPOINTMENT );
String nbPlacesToTake = request.getParameter( PARAMETER_NB_PLACE_TO_TAKE );
boolean bError = false;
if ( StringUtils.isNotEmpty( strIdAppointment ) )
{
// If we want to change the date of an appointment
AppointmentDTO appointmentDTO = AppointmentService.buildAppointmentDTOFromIdAppointment( Integer.parseInt( strIdAppointment ) );
if ( appointmentDTO.getIsCancelled( ) )
{
addError( ERROR_MESSAGE_REPORT_APPOINTMENT, getLocale( ) );
bError = true;
}
else
{
_validatedAppointment = appointmentDTO;
AppointmentService.addAppointmentResponses( _validatedAppointment );
nbPlacesToTake = Integer.toString( _validatedAppointment.getNbBookedSeats( ) );
}
}
int nIdForm = Integer.parseInt( strIdForm );
AppointmentFormDTO appointmentForm = FormService.buildAppointmentFormWithoutReservationRule( nIdForm );
if ( !appointmentForm.getIsActive( ) )
{
addError( ERROR_MESSAGE_FORM_NOT_ACTIVE, getLocale( ) );
bError = true;
}
// Check if the date of display and the endDateOfDisplay are in the
// validity date range of the form
if ( appointmentForm.getDateStartValidity( ) == null )
{
addError( ERROR_MESSAGE_NO_STARTING_VALIDITY_DATE, getLocale( ) );
bError = true;
}
int nNbWeeksToDisplay = AppPropertiesService.getPropertyInt( PROPERTY_NB_WEEKS_TO_DISPLAY_IN_BO, appointmentForm.getNbWeeksToDisplay( ) );
LocalDate startingDateOfDisplay = LocalDate.now( ).minusWeeks( nNbWeeksToDisplay );
LocalDate endingDateOfDisplay = LocalDate.now( ).plusWeeks( nNbWeeksToDisplay );
if ( appointmentForm.getDateEndValidity( ) != null )
{
if ( startingDateOfDisplay.isAfter( endingDateOfDisplay ) )
{
addError( ERROR_MESSAGE_FORM_NO_MORE_VALID, getLocale( ) );
bError = true;
}
if ( endingDateOfDisplay.isAfter( appointmentForm.getDateEndValidity( ).toLocalDate( ) ) )
{
endingDateOfDisplay = appointmentForm.getDateEndValidity( ).toLocalDate( );
}
}
String strDateOfDisplay = request.getParameter( PARAMETER_DATE_OF_DISPLAY );
LocalDate dateOfDisplay = LocalDate.now( );
if ( StringUtils.isNotEmpty( strDateOfDisplay ) )
{
dateOfDisplay = LocalDate.parse( strDateOfDisplay );
}
List<Slot> listSlot = new ArrayList<>( );
List<WeekDefinition> listWeekDefinition = WeekDefinitionService.findListWeekDefinition( nIdForm );
Map<WeekDefinition, ReservationRule> mapReservationRule = ReservationRuleService.findAllReservationRule( nIdForm, listWeekDefinition );
List<ReservationRule> listReservationRules = new ArrayList<>( mapReservationRule.values( ) );
LocalTime maxEndingTime = WeekDefinitionService.getMaxEndingTimeOfAListOfWeekDefinition( listReservationRules );
LocalTime minStartingTime = WeekDefinitionService.getMinStartingTimeOfAListOfWeekDefinition( listReservationRules );
List<String> listDayOfWeek = new ArrayList<>( WeekDefinitionService.getSetDaysOfWeekOfAListOfWeekDefinitionForFullCalendar( listReservationRules ) );
if ( !bError )
{
boolean isNewNbPlacesToTake = ( nbPlacesToTake != null && StringUtils.isNumeric( nbPlacesToTake ) );
if ( appointmentForm.getIsMultislotAppointment( ) && ( ( _nNbPlacesToTake != 0 || isNewNbPlacesToTake ) && nbPlacesToTake != null ) )
{
_nNbPlacesToTake = isNewNbPlacesToTake ? Integer.parseInt( nbPlacesToTake ) : _nNbPlacesToTake;
listSlot = SlotService.buildListSlot( nIdForm, mapReservationRule, startingDateOfDisplay, endingDateOfDisplay, _nNbPlacesToTake,
appointmentForm.getBoOverbooking( ) && RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm,
AppointmentResourceIdService.PERMISSION_OVERBOOKING_FORM, (User) getUser( ) ) );
}
else
{
_nNbPlacesToTake = 0;
listSlot = SlotService.buildListSlot( nIdForm, mapReservationRule, startingDateOfDisplay, endingDateOfDisplay );
}
// Tag as passed the slots passed
List<Slot> listSlotsPassed = listSlot.stream( ).filter( s -> s.getEndingDateTime( ).isBefore( LocalDateTime.now( ) ) )
.collect( Collectors.toList( ) );
for ( Slot slotPassed : listSlotsPassed )
{
slotPassed.setIsPassed( Boolean.TRUE );
}
}
Map<String, Object> model = getModel( );
if ( bError )
{
model.put( MARK_FORM_CALENDAR_ERRORS, bError );
}
// If we change the date of an appointment
// filter the list of slot with only the ones that have enough places at
// the moment of the edition
if ( _validatedAppointment != null )
{
int nbBookedSeats = _validatedAppointment.getNbBookedSeats( );
listSlot = listSlot.stream( ).filter( s -> s.getNbPotentialRemainingPlaces( ) >= nbBookedSeats && s.getIsOpen( ) ).collect( Collectors.toList( ) );
model.put( MARK_MODIFICATION_DATE_APPOINTMENT, true );
}
else
{
model.put( MARK_MODIFICATION_DATE_APPOINTMENT, false );
}
model.put( MARK_FORM, appointmentForm );
model.put( PARAMETER_ID_FORM, nIdForm );
model.put( MARK_FORM_MESSAGES, FormMessageService.findFormMessageByIdForm( nIdForm ) );
model.put( PARAMETER_STARTING_DATE_OF_DISPLAY, startingDateOfDisplay );
model.put( PARAMETER_STR_STARTING_DATE_OF_DISPLAY, startingDateOfDisplay.format( Utilities.getFormatter( ) ) );
model.put( PARAMETER_ENDING_DATE_OF_DISPLAY, endingDateOfDisplay );
model.put( PARAMETER_STR_ENDING_DATE_OF_DISPLAY, endingDateOfDisplay.format( Utilities.getFormatter( ) ) );
model.put( PARAMETER_DATE_OF_DISPLAY, dateOfDisplay );
model.put( PARAMETER_DAY_OF_WEEK, listDayOfWeek );
model.put( PARAMETER_EVENTS, listSlot );
model.put( PARAMETER_EVENTS_COMMENTS, CommentService
.buildCommentDTO( CommentService.finListComments( Date.valueOf( startingDateOfDisplay ), Date.valueOf( endingDateOfDisplay ), nIdForm ) ) );
model.put( PARAMETER_MIN_TIME, minStartingTime );
model.put( PARAMETER_MAX_TIME, maxEndingTime );
model.put( PARAMETER_MIN_DURATION, LocalTime.MIN.plusMinutes( AppointmentUtilities.THIRTY_MINUTES ) );
model.put( MARK_FORM_OVERBOOKING_ALLOWED, appointmentForm.getBoOverbooking( ) && RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm,
AppointmentResourceIdService.PERMISSION_OVERBOOKING_FORM, (User) getUser( ) ) );
model.put( MARK_LOCALE, getLocale( ) );
model.put( MARK_MAILING_LIST, AdminMailingListService.getMailingLists( getUser( ) ) );
model.put( AppointmentUtilities.MARK_PERMISSION_ADD_COMMENT, String.valueOf( RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE,
String.valueOf( appointmentForm.getIdForm( ) ), AppointmentResourceIdService.PERMISSION_ADD_COMMENT_FORM, (User) getUser( ) ) ) );
model.put( AppointmentUtilities.MARK_PERMISSION_MODERATE_COMMENT, String.valueOf( RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE,
String.valueOf( appointmentForm.getIdForm( ) ), AppointmentResourceIdService.PERMISSION_MODERATE_COMMENT_FORM, (User) getUser( ) ) ) );
model.put( AppointmentUtilities.MARK_PERMISSION_ACCESS_CODE, getUser( ).getAccessCode( ) );
model.put( MARK_APPOINTMENT_DESK_ENABLED, ( _moduleAppointmentDesk != null && _moduleAppointmentDesk.isInstalled( ) ) );
if ( appointmentForm.getIsMultislotAppointment( ) && _nNbPlacesToTake <= 0 )
{
return getPage( PROPERTY_PAGE_TITLE_MANAGE_APPOINTMENTS_CALENDAR, TEMPLATE_MANAGE_APPOINTMENTS_CALENDAR_MULTI_SLOT, model );
}
else
if ( appointmentForm.getIsMultislotAppointment( ) && _nNbPlacesToTake >= 1 )
{
return getPage( PROPERTY_PAGE_TITLE_MANAGE_APPOINTMENTS_CALENDAR, TEMPLATE_MANAGE_APPOINTMENTS_CALENDAR_GROUPED, model );
}
else
{
return getPage( PROPERTY_PAGE_TITLE_MANAGE_APPOINTMENTS_CALENDAR, TEMPLATE_MANAGE_APPOINTMENTS_CALENDAR, model );
}
}
/**
* Get the page to manage appointments
*
* @param request
* The request
* @return The HTML code to display
* @throws AccessDeniedException
*/
@View( value = VIEW_MANAGE_APPOINTMENTS )
public synchronized String getManageAppointments( HttpServletRequest request ) throws AccessDeniedException
{
String strIdForm = request.getParameter( PARAMETER_ID_FORM );
if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm, AppointmentResourceIdService.PERMISSION_VIEW_FORM, (User) getUser( ) ) )
{
throw new AccessDeniedException( AppointmentResourceIdService.PERMISSION_VIEW_FORM );
}
String strModifDateAppointment = request.getParameter( PARAMETER_MODIF_DATE );
if ( strModifDateAppointment != null && Boolean.parseBoolean( strModifDateAppointment ) )
{
return getViewChangeDateAppointment( request );
}
// Clean session
AppointmentAsynchronousUploadHandler.getHandler( ).removeSessionFiles( request.getSession( ) );
_notValidatedAppointment = null;
_validatedAppointment = null;
_appointmentForm = null;
int nIdForm = Integer.parseInt( strIdForm );
// If it is a new search
if ( request.getParameter( PARAMETER_SEARCH ) != null )
{
// Populate the filter
populate( _filter, request );
}
else
if ( request.getParameter( PARAMETER_RESET ) != null || _filter == null || _filter.getIdForm( ) != nIdForm )
{
_filter = new AppointmentFilterDTO( );
_filter.setIdForm( nIdForm );
// if we come from the calendar, need to get the starting and ending
// time of the slot
String strStartingDateTime = request.getParameter( PARAMETER_STARTING_DATE_TIME );
String strEndingDateTime = request.getParameter( PARAMETER_ENDING_DATE_TIME );
if ( strStartingDateTime != null && strEndingDateTime != null )
{
LocalDateTime startingDateTime = LocalDateTime.parse( strStartingDateTime );
LocalDateTime endingDateTime = LocalDateTime.parse( strEndingDateTime );
_filter.setStartingDateOfSearch( Date.valueOf( startingDateTime.toLocalDate( ) ) );
_filter.setStartingTimeOfSearch( startingDateTime.toLocalTime( ).toString( ) );
_filter.setEndingDateOfSearch( Date.valueOf( endingDateTime.toLocalDate( ) ) );
_filter.setEndingTimeOfSearch( endingDateTime.toLocalTime( ).toString( ) );
}
}
_strCurrentPageIndex = AbstractPaginator.getPageIndex( request, AbstractPaginator.PARAMETER_PAGE_INDEX, _strCurrentPageIndex );
String strOrderBy = request.getParameter( PARAMETER_ORDER_BY );
String strOrderAsc = request.getParameter( PARAMETER_ORDER_ASC );
if ( strOrderBy == null )
{
strOrderBy = DATE_APPOINTMENT;
}
boolean bAsc = Boolean.FALSE;
if ( strOrderAsc != null )
{
bAsc = Boolean.parseBoolean( strOrderAsc );
}
_filter.setOrderBy( strOrderBy );
_filter.setOrderAsc( bAsc );
if ( _strCurrentPageIndex == null )
{
_strCurrentPageIndex = DEFAULT_CURRENT_PAGE;
}
if ( DEFAULT_CURRENT_PAGE.equals( _strCurrentPageIndex ) )
{
_listAppointmentsIds = AppointmentService.findListAppointmentsIdsByFilter( _filter );
}
_nItemsPerPage = AbstractPaginator.getItemsPerPage( request, AbstractPaginator.PARAMETER_ITEMS_PER_PAGE, _nItemsPerPage, _nDefaultItemsPerPage );
List<AppointmentDTO> listAppointmentsDTO = findListAppointmentsDTOByFilterByPage( );
// If it is an order by
listAppointmentsDTO = orderList( listAppointmentsDTO );
if ( StringUtils.isNotEmpty( request.getParameter( PARAMETER_DELETE_AND_BACK ) ) )
{
String [ ] tabIdAppointmentToDelete = request.getParameterValues( PARAMETER_ID_APPOINTMENT_DELETE );
if ( tabIdAppointmentToDelete != null )
{
request.getSession( ).setAttribute( PARAMETER_ID_APPOINTMENT_DELETE, tabIdAppointmentToDelete );
return getConfirmRemoveMassAppointment( request, nIdForm );
}
}
UrlItem url = new UrlItem( JSP_MANAGE_APPOINTMENTS );
url.addParameter( MVCUtils.PARAMETER_VIEW, VIEW_MANAGE_APPOINTMENTS );
url.addParameter( PARAMETER_ID_FORM, strIdForm );
String strUrl = url.getUrl( );
LocalizedPaginator<Integer> paginator = new LocalizedPaginator<>(_listAppointmentsIds, _nItemsPerPage, strUrl, PARAMETER_PAGE_INDEX,
_strCurrentPageIndex, getLocale( ) );
AppointmentFormDTO form = FormService.buildAppointmentFormLight( nIdForm );
Map<String, Object> model = getModel( );
model.put( MARK_FORM, form );
model.put( MARK_FORM_MESSAGES, FormMessageService.findFormMessageByIdForm( nIdForm ) );
model.put( MARK_NB_ITEMS_PER_PAGE, Integer.toString( _nItemsPerPage ) );
model.put( MARK_PAGINATOR, paginator );
model.put( MARK_LANGUAGE, getLocale( ) );
model.put( MARK_ACTIVATE_WORKFLOW, ACTIVATEWORKFLOW );
if ( ( form.getIdWorkflow( ) > 0 ) && WorkflowService.getInstance( ).isAvailable( ) )
{
StateService stateService = SpringContextService.getBean( StateService.BEAN_SERVICE );
int nIdWorkflow = form.getIdWorkflow( );
StateFilter stateFilter = new StateFilter( );
stateFilter.setIdWorkflow( nIdWorkflow );
for ( AppointmentDTO appointment : listAppointmentsDTO )
{
State stateAppointment = stateService.findByResource( appointment.getIdAppointment( ), Appointment.APPOINTMENT_RESOURCE_TYPE, nIdWorkflow );
if ( stateAppointment != null )
{
appointment.setState( stateAppointment );
}
appointment.setListWorkflowActions( WorkflowService.getInstance( ).getActions( appointment.getIdAppointment( ),
Appointment.APPOINTMENT_RESOURCE_TYPE, form.getIdWorkflow( ), (User) getUser( ) ) );
}
}
User user = getUser( );
model.put( MARK_APPOINTMENT_LIST, listAppointmentsDTO );
model.put( MARK_FILTER, _filter );
model.put( MARK_LIST_STATUS, getListStatus( ) );
model.put( MARK_RIGHT_CREATE,
RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm, AppointmentResourceIdService.PERMISSION_CREATE_APPOINTMENT, user ) );
model.put( MARK_RIGHT_DELETE,
RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm, AppointmentResourceIdService.PERMISSION_DELETE_APPOINTMENT, user ) );
model.put( MARK_RIGHT_VIEW,
RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm, AppointmentResourceIdService.PERMISSION_VIEW_APPOINTMENT, user ) );
model.put( MARK_RIGHT_CHANGE_STATUS, RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm,
AppointmentResourceIdService.PERMISSION_CHANGE_APPOINTMENT_STATUS, user ) );
model.put( MARK_DEFAULT_FIELD_LIST, AppointmentExportService.getDefaultColumnList( getLocale( ) ) );
model.put( MARK_CUSTOM_FIELD_LIST, AppointmentExportService.getCustomColumnList( strIdForm ) );
model.put( MARK_LOCALE, getLocale( ) );
model.put( MARK_APPOINTMENT_DESK_ENABLED, ( _moduleAppointmentDesk != null && _moduleAppointmentDesk.isInstalled( ) ) );
return getPage( PROPERTY_PAGE_TITLE_MANAGE_APPOINTMENTS, TEMPLATE_MANAGE_APPOINTMENTS, model );
}
/**
* Manages the removal form of a appointment whose identifier is in the HTTP request
*
* @param request
* The HTTP request
* @return the HTML code to confirm
*/
@Action( ACTION_CONFIRM_REMOVE_APPOINTMENT )
public synchronized String getConfirmRemoveAppointment( HttpServletRequest request )
{
UrlItem url = new UrlItem( getActionUrl( ACTION_REMOVE_APPOINTMENT ) );
url.addParameter( PARAMETER_ID_APPOINTMENT, request.getParameter( PARAMETER_ID_APPOINTMENT ) );
url.addParameter( PARAMETER_ID_FORM, request.getParameter( PARAMETER_ID_FORM ) );
String strMessageUrl = AdminMessageService.getMessageUrl( request, MESSAGE_CONFIRM_REMOVE_APPOINTMENT, url.getUrl( ), AdminMessage.TYPE_CONFIRMATION );
return redirect( request, strMessageUrl );
}
/**
* Handles the removal form of a appointment
*
* @param request
* The HTTP request
* @return the JSP URL to display the form to manage appointments
* @throws AccessDeniedException
* If the user is not authorized to access this feature
*/
@Action( ACTION_REMOVE_APPOINTMENT )
public synchronized String doRemoveAppointment( HttpServletRequest request ) throws AccessDeniedException
{
int nIdAppointment = Integer.parseInt( request.getParameter( PARAMETER_ID_APPOINTMENT ) );
Integer idForm = Integer.parseInt( request.getParameter( PARAMETER_ID_FORM ) );
if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, Integer.toString( idForm ),
AppointmentResourceIdService.PERMISSION_DELETE_APPOINTMENT, (User) getUser( ) ) )
{
throw new AccessDeniedException( AppointmentResourceIdService.PERMISSION_DELETE_APPOINTMENT );
}
AppointmentService.deleteAppointment( nIdAppointment );
AppLogService.info( LogUtilities.buildLog( ACTION_REMOVE_APPOINTMENT, Integer.toString( nIdAppointment ), getUser( ) ) );
addInfo( INFO_APPOINTMENT_REMOVED, getLocale( ) );
return redirect( request, VIEW_MANAGE_APPOINTMENTS, PARAMETER_ID_FORM, idForm );
}
/**
* Manages the removal form of a appointment whose identifier is in the HTTP request
*
* @param request
* The HTTP request
* @return the HTML code to confirm
*/
@Action( ACTION_CONFIRM_REMOVE_MASS_APPOINTMENT )
public synchronized String getConfirmRemoveMassAppointment( HttpServletRequest request, int nIdForm )
{
UrlItem url = new UrlItem( getActionUrl( ACTION_REMOVE_MASSAPPOINTMENT ) );
url.addParameter( PARAMETER_ID_FORM, nIdForm );
String strMessageUrl = AdminMessageService.getMessageUrl( request, MESSAGE_CONFIRM_REMOVE_MASSAPPOINTMENT, url.getUrl( ),
AdminMessage.TYPE_CONFIRMATION );
return redirect( request, strMessageUrl );
}
/**
* Handles the removal form of a appointment
*
* @param request
* The HTTP request
* @return the JSP URL to display the form to manage appointments
* @throws AccessDeniedException
* If the user is not authorized to access this feature
*/
@Action( ACTION_REMOVE_MASSAPPOINTMENT )
public synchronized String doRemoveMassAppointment( HttpServletRequest request ) throws AccessDeniedException
{
String [ ] tabIdAppointmentToDelete = (String [ ]) request.getSession( ).getAttribute( PARAMETER_ID_APPOINTMENT_DELETE );
request.getSession( ).removeAttribute( PARAMETER_ID_APPOINTMENT_DELETE );
Integer idForm = Integer.parseInt( request.getParameter( PARAMETER_ID_FORM ) );
if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, Integer.toString( idForm ),
AppointmentResourceIdService.PERMISSION_DELETE_APPOINTMENT, (User) getUser( ) ) )
{
throw new AccessDeniedException( AppointmentResourceIdService.PERMISSION_DELETE_APPOINTMENT );
}
if ( tabIdAppointmentToDelete != null )
{
for ( String strIdAppointment : tabIdAppointmentToDelete )
{
AppointmentService.deleteAppointment( Integer.valueOf( strIdAppointment ) );
AppLogService.info( LogUtilities.buildLog( ACTION_REMOVE_APPOINTMENT, strIdAppointment, getUser( ) ) );
}
addInfo( INFO_APPOINTMENT_MASSREMOVED, getLocale( ) );
}
return redirect( request, VIEW_MANAGE_APPOINTMENTS, PARAMETER_ID_FORM, idForm );
}
/**
* View details of an appointment
*
* @param request
* The request
* @return The HTML content to display
* @throws AccessDeniedException
* If the user is not authorized to access this feature
* @throws FileServiceException
* If there is an error with the file service
*/
@View( VIEW_VIEW_APPOINTMENT )
public synchronized String getViewAppointment( HttpServletRequest request ) throws AccessDeniedException, FileServiceException
{
String strIdAppointment = request.getParameter( PARAMETER_ID_APPOINTMENT );
String strIdForm = request.getParameter( PARAMETER_ID_FORM );
int nIdForm = Integer.parseInt( strIdForm );
Form form = FormService.findFormLightByPrimaryKey( nIdForm );
int nItemsPerPage = AbstractPaginator.getItemsPerPage( request, AbstractPaginator.PARAMETER_ITEMS_PER_PAGE, _nItemsPerPage, _nDefaultItemsPerPage );
int nIdAppointment = Integer.parseInt( strIdAppointment );
AppointmentDTO appointmentDTO = AppointmentService.buildAppointmentDTOFromIdAppointment( nIdAppointment );
if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm, AppointmentResourceIdService.PERMISSION_VIEW_APPOINTMENT,
(User) getUser( ) ) )
{
throw new AccessDeniedException( AppointmentResourceIdService.PERMISSION_VIEW_APPOINTMENT );
}
Map<String, Object> model = getModel( );
model.put( MARK_APPOINTMENT, appointmentDTO );
if ( appointmentDTO.getAdminUserCreate( ) != null )
{
model.put( MARK_USER_CREATOR, AdminUserHome.findUserByLogin( appointmentDTO.getAdminUserCreate( ) ) );
}
model.put( MARK_FORM_MESSAGES, FormMessageService.findFormMessageByIdForm( nIdForm ) );
model.put( MARK_FORM, form );
model.put( MARK_NB_ITEMS_PER_PAGE, Integer.toString( nItemsPerPage ) );
if ( ( form.getIdWorkflow( ) > 0 ) && WorkflowService.getInstance( ).isAvailable( ) )
{
model.put( MARK_RESOURCE_HISTORY, WorkflowService.getInstance( ).getDisplayDocumentHistory( nIdAppointment, Appointment.APPOINTMENT_RESOURCE_TYPE,
form.getIdWorkflow( ), request, getLocale( ), (User) getUser( ) ) );
}
if ( ( form.getIdWorkflow( ) > 0 ) && WorkflowService.getInstance( ).isAvailable( ) )
{
StateService stateService = SpringContextService.getBean( StateService.BEAN_SERVICE );
int nIdWorkflow = form.getIdWorkflow( );
StateFilter stateFilter = new StateFilter( );
stateFilter.setIdWorkflow( nIdWorkflow );
State stateAppointment = stateService.findByResource( appointmentDTO.getIdAppointment( ), Appointment.APPOINTMENT_RESOURCE_TYPE, nIdWorkflow );
if ( stateAppointment != null )
{
appointmentDTO.setState( stateAppointment );
}
appointmentDTO.setListWorkflowActions( WorkflowService.getInstance( ).getActions( appointmentDTO.getIdAppointment( ),
Appointment.APPOINTMENT_RESOURCE_TYPE, form.getIdWorkflow( ), (User) getUser( ) ) );
}
Locale locale = getLocale( );
List<Response> listResponse = AppointmentResponseService.findListResponse( nIdAppointment );
for ( Response response : listResponse )
{
if ( response.getFile( ) != null )
{
IFileStoreServiceProvider fileStoreService = FileService.getInstance( ).getFileStoreServiceProvider( );
File file = null;
try
{
file = fileStoreService.getFile( response.getFile( ).getFileKey( ) );
}
catch( FileServiceException e )
{
AppLogService.error( "Error get file: " + response.getFile( ).getFileKey( ), e );
}
response.setFile( file );
}
if ( response.getEntry( ) != null )
{
response.setEntry( EntryHome.findByPrimaryKey( response.getEntry( ).getIdEntry( ) ) );
}
}
appointmentDTO.setListResponse( listResponse );
model.put( MARK_LIST_RESPONSE_RECAP_DTO, AppointmentUtilities.buildListResponse( appointmentDTO, request, locale ) );
model.put( MARK_ADDON, AppointmentAddOnManager.getAppointmentAddOn( appointmentDTO.getIdAppointment( ), getLocale( ) ) );
User user = getUser( );
model.put( MARK_RIGHT_CREATE,
RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm, AppointmentResourceIdService.PERMISSION_CREATE_APPOINTMENT, user ) );
model.put( MARK_RIGHT_DELETE,
RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm, AppointmentResourceIdService.PERMISSION_DELETE_APPOINTMENT, user ) );
model.put( MARK_RIGHT_VIEW,
RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm, AppointmentResourceIdService.PERMISSION_VIEW_APPOINTMENT, user ) );
model.put( MARK_RIGHT_CHANGE_STATUS, RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm,
AppointmentResourceIdService.PERMISSION_CHANGE_APPOINTMENT_STATUS, user ) );
model.put( MARK_LANGUAGE, getLocale( ) );
model.put( MARK_ACTIVATE_WORKFLOW, ACTIVATEWORKFLOW );
model.put( MARK_LOCALE, getLocale( ) );
return getPage( PROPERTY_PAGE_TITLE_VIEW_APPOINTMENT, TEMPLATE_VIEW_APPOINTMENT, model );
}
/**
* Do download a file from an appointment response
*
* @param request
* The request
* @param response
* The response
* @return nothing.
* @throws AccessDeniedException
* If the user is not authorized to access this feature
*/
@Action( ACTION_EXPORT_APPOINTMENTS )
public synchronized String doExportAppointments( HttpServletRequest request ) throws AccessDeniedException
{
String strIdForm = request.getParameter( PARAMETER_ID_FORM );
if ( StringUtils.isEmpty( strIdForm ) || !StringUtils.isNumeric( strIdForm ) )
{
return redirect( request, AppointmentFormJspBean.getURLManageAppointmentForms( request ) );
}
if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm, AppointmentResourceIdService.PERMISSION_VIEW_APPOINTMENT,
(User) getUser( ) ) )
{
throw new AccessDeniedException( AppointmentResourceIdService.PERMISSION_VIEW_APPOINTMENT );
}
Locale locale = getLocale( );
List<AppointmentDTO> listAppointmentsDTO = new ArrayList<>( );
if ( _filter != null && _filter.getIdForm( ) == Integer.parseInt( strIdForm ) )
{
listAppointmentsDTO = AppointmentService.findListAppointmentsDTOByFilter( _filter );
}
List<String> defaultColumnList = new ArrayList<>( );
List<Integer> customColumnList = new ArrayList<>( );
if ( ArrayUtils.isNotEmpty( request.getParameterValues( PARAMETER_SELECTED_DEFAULT_FIELD ) ) )
{
defaultColumnList = Arrays.asList( request.getParameterValues( PARAMETER_SELECTED_DEFAULT_FIELD ) );
}
if ( ArrayUtils.isNotEmpty( request.getParameterValues( PARAMETER_SELECTED_CUSTOM_FIELD ) ) )
{
customColumnList = Arrays.asList( request.getParameterValues( PARAMETER_SELECTED_CUSTOM_FIELD ) ).stream( ).map( Integer::parseInt )
.collect( Collectors.toList( ) );
}
ExcelAppointmentGenerator generator = new ExcelAppointmentGenerator( defaultColumnList, locale, listAppointmentsDTO, customColumnList );
TemporaryFileGeneratorService.getInstance( ).generateFile( generator, getUser( ) );
addInfo( "appointment.export.async.message", getLocale( ) );
return getManageAppointments( request );
}
/**
* Returns the form to create an appointment
*
* @param request
* The HTTP request
* @return the HTML code of the appointment form
* @throws AccessDeniedException
* If the user is not authorized to access this feature
*/
@View( VIEW_CREATE_APPOINTMENT )
public synchronized String getViewCreateAppointment( HttpServletRequest request ) throws AccessDeniedException
{
clearUploadFilesIfNeeded( request.getSession( ) );
String strIdForm = request.getParameter( PARAMETER_ID_FORM );
int nIdForm = Integer.parseInt( strIdForm );
String strNbPlacesToTake = request.getParameter( PARAMETER_NB_PLACE_TO_TAKE );
if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm, AppointmentResourceIdService.PERMISSION_CREATE_APPOINTMENT,
(User) getUser( ) ) )
{
throw new AccessDeniedException( AppointmentResourceIdService.PERMISSION_CREATE_APPOINTMENT );
}
FormRule formRule = FormRuleService.findFormRuleWithFormId( nIdForm );
Locale locale = getLocale( );
String isModification = request.getParameter( PARAMETER_IS_MODIFICATION );
boolean bModificationForm = false;
List<Slot> listSlot = null;
if ( isModification != null )
{
bModificationForm = true;
}
else
{
if ( strNbPlacesToTake != null )
{
_nNbPlacesToTake = Integer.parseInt( strNbPlacesToTake );
}
int nNbConsecutiveSlot = ( _nNbPlacesToTake == 0 ) ? 1 : _nNbPlacesToTake;
LocalDateTime startingDateTime = LocalDateTime.parse( request.getParameter( PARAMETER_STARTING_DATE_TIME ) );
// Get all the week definitions
List<WeekDefinition> listWeekDefinition = WeekDefinitionService.findListWeekDefinition( nIdForm );
Map<WeekDefinition, ReservationRule> mapReservationRule = ReservationRuleService.findAllReservationRule( nIdForm, listWeekDefinition );
listSlot = SlotService.buildListSlot( nIdForm, mapReservationRule, startingDateTime.toLocalDate( ), startingDateTime.toLocalDate( ) );
if ( formRule.getBoOverbooking( ) && RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm,
AppointmentResourceIdService.PERMISSION_OVERBOOKING_FORM, (User) getUser( ) ) )
{
listSlot = listSlot.stream( ).filter( s -> ( ( startingDateTime.compareTo( s.getStartingDateTime( ) ) <= 0 ) && ( s.getIsOpen( ) ) ) )
.limit( nNbConsecutiveSlot ).collect( Collectors.toList( ) );
}
else
{
listSlot = listSlot.stream( ).filter(
s -> ( ( startingDateTime.compareTo( s.getStartingDateTime( ) ) <= 0 ) && ( s.getNbRemainingPlaces( ) > 0 ) && ( s.getIsOpen( ) ) ) )
.limit( nNbConsecutiveSlot ).collect( Collectors.toList( ) );
}
if ( listSlot == null || listSlot.stream( ).noneMatch( slot -> slot.getStartingDateTime( ).isEqual( startingDateTime ) )
|| ( _nNbPlacesToTake > 0 && _nNbPlacesToTake != listSlot.size( ) ) || !AppointmentUtilities.isConsecutiveSlots( listSlot ) )
{
addError( ERROR_MESSAGE_SLOT_FULL, locale );
return redirect( request, VIEW_CALENDAR_MANAGE_APPOINTMENTS, PARAMETER_ID_FORM, nIdForm );
}
}
// Get the not validated appointment in session if it exists
if ( _notValidatedAppointment == null )
{
if ( _validatedAppointment != null )
{
// Try to get the validated appointment in session
// (in case the user click on back button in the recap view (or
// modification)
_notValidatedAppointment = _validatedAppointment;
_validatedAppointment = null;
}
else
{
// Need to get back the informations the user has entered
_notValidatedAppointment = new AppointmentDTO( );
}
}
else
if ( _nNbPlacesToTake == 0 && bModificationForm )
{
_nNbPlacesToTake = _notValidatedAppointment.getNbBookedSeats( );
}
if ( !bModificationForm )
{
boolean bool = true;
_notValidatedAppointment.setSlot( null );
_notValidatedAppointment.setIdForm( nIdForm );
_notValidatedAppointment.setNbMaxPotentialBookedSeats( 0 );
for ( Slot slot : listSlot )
{
if ( slot.getIdSlot( ) == 0 )
{
slot = SlotSafeService.createSlot( slot );
}
else
{
slot = SlotService.findSlotById( slot.getIdSlot( ) );
}
// Need to check competitive access
// May be the slot is already taken at the same time
if ( slot.getNbPotentialRemainingPlaces( ) <= 0 && !formRule.getBoOverbooking( ) && !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE,
strIdForm, AppointmentResourceIdService.PERMISSION_OVERBOOKING_FORM, (User) getUser( ) ) )
{
_notValidatedAppointment = null;
addError( ERROR_MESSAGE_SLOT_FULL, locale );
return redirect( request, VIEW_CALENDAR_MANAGE_APPOINTMENTS, PARAMETER_ID_FORM, nIdForm );
}
_notValidatedAppointment.addSlot( slot );
if ( bool )
{
LocalDateTime startingDateTime = LocalDateTime.parse( request.getParameter( PARAMETER_STARTING_DATE_TIME ) );
_notValidatedAppointment.setDateOfTheAppointment( slot.getDate( ).format( Utilities.getFormatter( ) ) );
_notValidatedAppointment.setEndingDateTime( listSlot.get( listSlot.size( ) - 1 ).getEndingDateTime( ) );
_notValidatedAppointment.setStartingDateTime( startingDateTime );
ReservationRule reservationRule = ReservationRuleService.findReservationRuleByIdFormAndClosestToDateOfApply( nIdForm, slot.getDate( ) );
_appointmentForm = FormService.buildAppointmentForm( nIdForm, reservationRule );
bool = false;
}
AppointmentUtilities.putTimerInSession( request, slot.getIdSlot( ), _notValidatedAppointment, _appointmentForm.getMaxPeoplePerAppointment( ) );
}
if ( _notValidatedAppointment.getNbMaxPotentialBookedSeats( ) == 0 && !formRule.getBoOverbooking( ) && !RBACService
.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm, AppointmentResourceIdService.PERMISSION_OVERBOOKING_FORM, (User) getUser( ) ) )
{
addError( ERROR_MESSAGE_SLOT_FULL, locale );
return redirect( request, VIEW_CALENDAR_MANAGE_APPOINTMENTS, PARAMETER_ID_FORM, nIdForm );
}
}
Map<String, Object> model = getModel( );
if ( CollectionUtils.isNotEmpty( listFormErrors ) )
{
model.put( MARK_FORM_ERRORS, listFormErrors );
listFormErrors = new ArrayList<>( );
}
List<Entry> listEntryFirstLevel = EntryService.getFilter( _appointmentForm.getIdForm( ), false );
StringBuilder strBuffer = new StringBuilder( );
for ( Entry entry : listEntryFirstLevel )
{
EntryService.getHtmlEntry( model, entry.getIdEntry( ), strBuffer, locale, false, _notValidatedAppointment );
}
boolean isOverbooking = !_appointmentForm.getIsMultislotAppointment( ) && formRule.getBoOverbooking( ) && RBACService
.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm, AppointmentResourceIdService.PERMISSION_OVERBOOKING_FORM, (User) getUser( ) );
model.put( MARK_STR_ENTRY, strBuffer.toString( ) );
model.put( MARK_FORM, _appointmentForm );
model.put( MARK_APPOINTMENT, _notValidatedAppointment );
model.put( PARAMETER_DATE_OF_DISPLAY, _notValidatedAppointment.getSlot( ).get( 0 ).getDate( ) );
model.put( MARK_PLACES, _notValidatedAppointment.getNbMaxPotentialBookedSeats( ) );
model.put( MARK_IS_OVERBOOKING, isOverbooking );
FormMessage formMessages = FormMessageService.findFormMessageByIdForm( nIdForm );
model.put( MARK_FORM_MESSAGES, formMessages );
model.put( MARK_LOCALE, locale );
model.put( MARK_LIST_ERRORS, AppointmentDTO.getAllErrors( locale ) );
HtmlTemplate templateForm = AppTemplateService.getTemplate( TEMPLATE_HTML_CODE_FORM_ADMIN, getLocale( ), model );
model.put( MARK_FORM_HTML, templateForm.getHtml( ) );
model.put( MARK_LOCALE, getLocale( ) );
return getPage( PROPERTY_PAGE_TITLE_CREATE_APPOINTMENT, TEMPLATE_CREATE_APPOINTMENT, model );
}
/**
* Do validate data entered by a user to fill a form
*
* @param request
* The request
* @return The next URL to redirect to
* @throws AccessDeniedException
* If the user is not authorized to access this feature
*/
@Action( ACTION_DO_VALIDATE_FORM )
public synchronized String doValidateForm( HttpServletRequest request ) throws AccessDeniedException
{
String strIdForm = request.getParameter( PARAMETER_ID_FORM );
int nIdForm = Integer.parseInt( strIdForm );
String strEmail = request.getParameter( PARAMETER_EMAIL );
String strEmailConfirm = request.getParameter( PARAMETER_EMAIL_CONFIRMATION );
Locale locale = getLocale( );
AppointmentUtilities.checkDateOfTheAppointmentIsNotBeforeNow( _notValidatedAppointment, locale, listFormErrors );
AppointmentUtilities.checkEmail( strEmail, strEmailConfirm, _appointmentForm, locale, listFormErrors );
if ( _appointmentForm.getBoOverbooking( ) && RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm,
AppointmentResourceIdService.PERMISSION_OVERBOOKING_FORM, (User) getUser( ) ) )
{
_notValidatedAppointment.setOverbookingAllowed( true );
}
int nbBookedSeats = _nNbPlacesToTake;
if ( _nNbPlacesToTake == 0 )
{
nbBookedSeats = AppointmentUtilities.checkAndReturnNbBookedSeats( request.getParameter( PARAMETER_NUMBER_OF_BOOKED_SEATS ), _appointmentForm,
_notValidatedAppointment, locale, listFormErrors );
}
if ( _appointmentForm.getEnableMandatoryEmail( )
&& !AppointmentUtilities.checkNbDaysBetweenTwoAppointmentsTaken( _notValidatedAppointment, strEmail, _appointmentForm ) )
{
addWarning( ERROR_MESSAGE_NB_MIN_DAYS_BETWEEN_TWO_APPOINTMENTS, locale );
}
if ( _appointmentForm.getEnableMandatoryEmail( )
&& !AppointmentUtilities.checkNbMaxAppointmentsOnAGivenPeriod( _notValidatedAppointment, strEmail, _appointmentForm ) )
{
addWarning( ERROR_MESSAGE_NB_MAX_APPOINTMENTS_ON_A_PERIOD, locale );
}
List<AppointmentDTO> listAppointments = new ArrayList<>( );
if ( _appointmentForm.getEnableMandatoryEmail( )
&& !AppointmentUtilities.checkNbMaxAppointmentsDefinedOnCategory( _notValidatedAppointment, strEmail, _appointmentForm, listAppointments ) )
{
StringJoiner builder = new StringJoiner( StringUtils.SPACE );
String lf = System.getProperty( "line.separator" );
for ( AppointmentDTO appt : listAppointments )
{
builder.add( appt.getLastName( ) );
builder.add( appt.getFirstName( ) );
builder.add( appt.getDateOfTheAppointment( ) );
builder.add( appt.getStartingTime( ).toString( ) );
builder.add( lf );
}
Object [ ] tabAppointment = {
builder.toString( )
};
String strErrorMessageDateWithAppointments = I18nService.getLocalizedString( ERROR_MESSAGE_NB_MAX_APPOINTMENTS_ON_A_CATEGORY, tabAppointment,
locale );
addWarning( strErrorMessageDateWithAppointments );
}
AppointmentUtilities.fillAppointmentDTO( _notValidatedAppointment, nbBookedSeats, strEmail, strEmailConfirm, request.getParameter( PARAMETER_FIRST_NAME ),
request.getParameter( PARAMETER_LAST_NAME ) );
AppointmentUtilities.validateFormAndEntries( _notValidatedAppointment, request, listFormErrors, true );
AppointmentUtilities.fillInListResponseWithMapResponse( _notValidatedAppointment );
AppointmentUtilities.setAppointmentPhoneNumberValuesFromResponse( _notValidatedAppointment );
if ( CollectionUtils.isNotEmpty( listFormErrors ) )
{
LinkedHashMap<String, String> additionalParameters = new LinkedHashMap<>( );
additionalParameters.put( PARAMETER_ID_FORM, strIdForm );
additionalParameters.put( PARAMETER_STARTING_DATE_TIME, _notValidatedAppointment.getStartingDateTime( ).toString( ) );
additionalParameters.put( PARAMETER_ENDING_DATE_TIME, _notValidatedAppointment.getEndingDateTime( ).toString( ) );
return redirect( request, VIEW_CREATE_APPOINTMENT, additionalParameters );
}
_validatedAppointment = _notValidatedAppointment;
_notValidatedAppointment = null;
return redirect( request, VIEW_DISPLAY_RECAP_APPOINTMENT, PARAMETER_ID_FORM, nIdForm );
}
/**
* Return to the display recap view with the new date selected on the calendar
*
* @param request
* the request
* @return to the display recap view
* @throws FileServiceException
* If there is an error with the file service
*/
@View( VIEW_CHANGE_DATE_APPOINTMENT )
public synchronized String getViewChangeDateAppointment( HttpServletRequest request )
{
String strIdForm = request.getParameter( PARAMETER_ID_FORM );
Locale locale = getLocale( );
int nIdForm = Integer.parseInt( strIdForm );
LocalDateTime startingDateTime = LocalDateTime.parse( request.getParameter( PARAMETER_STARTING_DATE_TIME ) );
LocalDateTime endingDateTime = LocalDateTime.parse( request.getParameter( PARAMETER_ENDING_DATE_TIME ) );
// Get all the week definitions
List<WeekDefinition> listWeekDefinition = WeekDefinitionService.findListWeekDefinition( nIdForm );
Map<WeekDefinition, ReservationRule> mapReservationRule = ReservationRuleService.findAllReservationRule( nIdForm, listWeekDefinition );
List<Slot> listSlot = SlotService.buildListSlot( nIdForm, mapReservationRule, startingDateTime.toLocalDate( ), endingDateTime.toLocalDate( ) );
FormRule formRule = FormRuleService.findFormRuleWithFormId( nIdForm );
if ( formRule.getBoOverbooking( ) && RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm,
AppointmentResourceIdService.PERMISSION_OVERBOOKING_FORM, (User) getUser( ) ) )
{
listSlot = listSlot.stream( ).filter( s -> ( ( startingDateTime.compareTo( s.getStartingDateTime( ) ) <= 0 )
&& ( endingDateTime.compareTo( s.getEndingDateTime( ) ) >= 0 ) && ( s.getIsOpen( ) ) ) ).collect( Collectors.toList( ) );
}
else
{
listSlot = listSlot.stream( )
.filter( s -> ( ( startingDateTime.compareTo( s.getStartingDateTime( ) ) <= 0 )
&& ( endingDateTime.compareTo( s.getEndingDateTime( ) ) >= 0 ) && ( s.getNbRemainingPlaces( ) > 0 ) && ( s.getIsOpen( ) ) ) )
.collect( Collectors.toList( ) );
}
boolean bool = true;
// If nIdSlot == 0, the slot has not been created yet
_validatedAppointment.setSlot( null );
_validatedAppointment.setNbMaxPotentialBookedSeats( 0 );
for ( Slot slot : listSlot )
{
if ( slot.getIdSlot( ) == 0 )
{
slot = SlotSafeService.createSlot( slot );
}
else
{
slot = SlotService.findSlotById( slot.getIdSlot( ) );
}
if ( bool )
{
_validatedAppointment.setDateOfTheAppointment( slot.getDate( ).format( Utilities.getFormatter( ) ) );
ReservationRule reservationRule = ReservationRuleService.findReservationRuleByIdFormAndClosestToDateOfApply( nIdForm, slot.getDate( ) );
_appointmentForm = FormService.buildAppointmentForm( nIdForm, reservationRule );
bool = false;
}
// Need to check competitive access
// May be the slot is already taken at the same time
if ( slot.getNbPotentialRemainingPlaces( ) <= 0
&& ( !_appointmentForm.getBoOverbooking( ) || !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm,
AppointmentResourceIdService.PERMISSION_OVERBOOKING_FORM, (User) getUser( ) ) ) )
{
addError( ERROR_MESSAGE_SLOT_FULL, locale );
return redirect( request, VIEW_CALENDAR_MANAGE_APPOINTMENTS, PARAMETER_ID_FORM, nIdForm );
}
_validatedAppointment.addSlot( slot );
AppointmentUtilities.putTimerInSession( request, slot.getIdSlot( ), _validatedAppointment, _appointmentForm.getMaxPeoplePerAppointment( ) );
}
if ( _validatedAppointment.getNbMaxPotentialBookedSeats( ) == 0 && ( !_appointmentForm.getBoOverbooking( ) || !RBACService
.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm, AppointmentResourceIdService.PERMISSION_OVERBOOKING_FORM, (User) getUser( ) ) ) )
{
addError( ERROR_MESSAGE_SLOT_FULL, locale );
return redirect( request, VIEW_CALENDAR_MANAGE_APPOINTMENTS, PARAMETER_ID_FORM, nIdForm );
}
for ( Response response : _validatedAppointment.getListResponse( ) )
{
if ( response.getFile( ) != null )
{
IFileStoreServiceProvider fileStoreService = FileService.getInstance( ).getFileStoreServiceProvider( );
File file = null;
try
{
file = fileStoreService.getFile( response.getFile( ).getFileKey( ) );
}
catch( FileServiceException e )
{
AppLogService.error( "Error get file: " + response.getFile( ).getFileKey( ), e );
}
response.setFile( file );
}
}
Map<String, String> additionalParameters = new HashMap<>( );
additionalParameters.put( PARAMETER_ID_FORM, Integer.toString( nIdForm ) );
additionalParameters.put( PARAMETER_COME_FROM_CALENDAR, Boolean.TRUE.toString( ) );
return redirect( request, VIEW_DISPLAY_RECAP_APPOINTMENT, additionalParameters );
}
/**
* Display the recap before validating an appointment
*
* @param request
* The request
* @return The HTML content to display or the next URL to redirect to
*/
@View( VIEW_DISPLAY_RECAP_APPOINTMENT )
public synchronized String displayRecapAppointment( HttpServletRequest request )
{
Map<String, Object> model = getModel( );
String strComeFromCalendar = request.getParameter( PARAMETER_COME_FROM_CALENDAR );
if ( StringUtils.isNotEmpty( strComeFromCalendar ) )
{
model.put( PARAMETER_COME_FROM_CALENDAR, strComeFromCalendar );
model.put( PARAMETER_DATE_OF_DISPLAY, _validatedAppointment.getSlot( ).get( 0 ).getDate( ) );
}
model.put( MARK_FORM_MESSAGES, FormMessageService.findFormMessageByIdForm( _validatedAppointment.getIdForm( ) ) );
model.put( MARK_APPOINTMENT, _validatedAppointment );
Locale locale = getLocale( );
model.put( MARK_ADDON, AppointmentAddOnManager.getAppointmentAddOn( _validatedAppointment.getIdAppointment( ), getLocale( ) ) );
model.put( MARK_LIST_RESPONSE_RECAP_DTO, AppointmentUtilities.buildListResponse( _validatedAppointment, request, locale ) );
model.put( MARK_FORM, _appointmentForm );
model.put( MARK_LOCALE, getLocale( ) );
return getPage( PROPERTY_PAGE_TITLE_RECAP_APPOINTMENT, TEMPLATE_APPOINTMENT_FORM_RECAP, model );
}
/**
* Do save an appointment into the database if it is valid
*
* @param request
* The request
* @return The XPage to display
* @throws AccessDeniedException
* If the user is not authorized to access this feature
*/
@Action( ACTION_DO_MAKE_APPOINTMENT )
public synchronized String doMakeAppointment( HttpServletRequest request ) throws AccessDeniedException
{
boolean overbookingAllowed = false;
if ( StringUtils.isNotEmpty( request.getParameter( PARAMETER_BACK ) ) )
{
return redirect( request, VIEW_CREATE_APPOINTMENT, PARAMETER_ID_FORM, _validatedAppointment.getIdForm( ) );
}
if ( _appointmentForm.getBoOverbooking( ) && RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE,
Integer.toString( _appointmentForm.getIdForm( ) ), AppointmentResourceIdService.PERMISSION_OVERBOOKING_FORM, (User) getUser( ) ) )
{
overbookingAllowed = true;
}
if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, Integer.toString( _appointmentForm.getIdForm( ) ),
AppointmentResourceIdService.PERMISSION_CREATE_APPOINTMENT, (User) getUser( ) ) || !_appointmentForm.getIsActive( ) )
{
throw new AccessDeniedException( AppointmentResourceIdService.PERMISSION_CREATE_APPOINTMENT );
}
int nIdAppointment;
if ( _validatedAppointment.getIdAppointment( ) == 0 )
{
// set the admin user who is creating the appointment
AdminUser adminLuteceUser = AdminAuthenticationService.getInstance( ).getRegisteredUser( request );
_validatedAppointment.setAdminUserCreate( adminLuteceUser.getAccessCode( ) );
}
try
{
_validatedAppointment.setOverbookingAllowed( overbookingAllowed );
nIdAppointment = SlotSafeService.saveAppointment( _validatedAppointment, request );
}
catch( SlotFullException e )
{
addError( ERROR_MESSAGE_SLOT_FULL, getLocale( ) );
return redirect( request, VIEW_CALENDAR_MANAGE_APPOINTMENTS, PARAMETER_ID_FORM, _validatedAppointment.getIdForm( ) );
}
catch( SlotEditTaskExpiredTimeException e )
{
addError( ERROR_MESSAGE_SLOT_EDIT_TASK_EXPIRED_TIME, getLocale( ) );
return redirect( request, VIEW_CALENDAR_MANAGE_APPOINTMENTS, PARAMETER_ID_FORM, _validatedAppointment.getIdForm( ) );
}
catch( AppointmentSavedException e )
{
nIdAppointment = _validatedAppointment.getIdAppointment( );
AppLogService.error( "Error Save appointment: " + e.getMessage( ), e );
}
_nNbPlacesToTake = 0;
AppLogService.info( LogUtilities.buildLog( ACTION_DO_MAKE_APPOINTMENT, Integer.toString( nIdAppointment ), getUser( ) ) );
addInfo( INFO_APPOINTMENT_CREATED, getLocale( ) );
AppointmentAsynchronousUploadHandler.getHandler( ).removeSessionFiles( request.getSession( ) );
Map<String, String> additionalParameters = new HashMap<>( );
additionalParameters.put( PARAMETER_ID_FORM, Integer.toString( _appointmentForm.getIdForm( ) ) );
additionalParameters.put( PARAMETER_DATE_OF_DISPLAY, _validatedAppointment.getSlot( ).get( 0 ).getDate( ).toString( ) );
_validatedAppointment = null;
return redirect( request, VIEW_CALENDAR_MANAGE_APPOINTMENTS, additionalParameters );
}
/**
* Do download a file from an appointment response stored in session and not yet on server fs
*
* @param request
* The request
* @param httpResponse
* The response
* @return nothing.
* @throws AccessDeniedException
* If the user is not authorized to access this feature
*/
public synchronized String getDownloadFileFromSession( HttpServletRequest request, HttpServletResponse httpResponse ) throws AccessDeniedException
{
String strIdResponse = request.getParameter( PARAMETER_ID_RESPONSE );
File respfile = null;
if ( StringUtils.isEmpty( strIdResponse ) || !StringUtils.isNumeric( strIdResponse ) )
{
return redirect( request, AppointmentFormJspBean.getURLManageAppointmentForms( request ) );
}
int nIdResponse = Integer.parseInt( strIdResponse );
List<Response> lResponse = _validatedAppointment.getListResponse( );
for ( Response response : lResponse )
{
if ( response.getEntry( ).getIdEntry( ) == nIdResponse && response.getFile( ) != null )
{
respfile = response.getFile( );
break;
}
}
if ( respfile == null )
{
return redirect( request, AppointmentFormJspBean.getURLManageAppointmentForms( request ) );
}
httpResponse.setHeader( "Content-Disposition", "attachment; filename=\"" + respfile.getTitle( ) + "\";" );
httpResponse.setHeader( "Content-type", respfile.getMimeType( ) );
httpResponse.addHeader( "Content-Encoding", "UTF-8" );
httpResponse.addHeader( "Pragma", "public" );
httpResponse.addHeader( "Expires", "0" );
httpResponse.addHeader( "Cache-Control", "must-revalidate,post-check=0,pre-check=0" );
try
{
OutputStream os = httpResponse.getOutputStream( );
os.write( respfile.getPhysicalFile( ).getValue( ) );
// We do not close the output stream in finally clause because it is
// the response stream,
// and an error message needs to be displayed if an exception occurs
os.close( );
}
catch( IOException e )
{
AppLogService.error( e.getStackTrace( ), e );
}
return StringUtils.EMPTY;
}
/**
* Do download a file from an appointment response
*
* @param request
* The request
* @param httpResponse
* The response
* @return nothing.
* @throws AccessDeniedException
* If the user is not authorized to access this feature
* @throws FileServiceException
* If there is an error with the file service
*/
public synchronized String getDownloadFile( HttpServletRequest request, HttpServletResponse httpResponse ) throws AccessDeniedException, FileServiceException
{
String strIdResponse = request.getParameter( PARAMETER_ID_RESPONSE );
if ( StringUtils.isEmpty( strIdResponse ) || !StringUtils.isNumeric( strIdResponse ) )
{
return redirect( request, AppointmentFormJspBean.getURLManageAppointmentForms( request ) );
}
int nIdResponse = Integer.parseInt( strIdResponse );
Response response = ResponseHome.findByPrimaryKey( nIdResponse );
IFileStoreServiceProvider fileStoreService = FileService.getInstance( ).getFileStoreServiceProvider( );
File file = null;
try
{
file = fileStoreService.getFile( response.getFile( ).getFileKey( ) );
}
catch( FileServiceException e )
{
AppLogService.error( "Error get file: " + response.getFile( ).getFileKey( ), e );
}
httpResponse.setHeader( "Content-Disposition", "attachment; filename=\"" + file.getTitle( ) + "\";" );
httpResponse.setHeader( "Content-type", file.getMimeType( ) );
httpResponse.addHeader( "Content-Encoding", "UTF-8" );
httpResponse.addHeader( "Pragma", "public" );
httpResponse.addHeader( "Expires", "0" );
httpResponse.addHeader( "Cache-Control", "must-revalidate,post-check=0,pre-check=0" );
try
{
OutputStream os = httpResponse.getOutputStream( );
os.write( file.getPhysicalFile( ).getValue( ) );
// We do not close the output stream in finnaly clause because it is
// the response stream,
// and an error message needs to be displayed if an exception occurs
os.close( );
}
catch( IOException e )
{
AppLogService.error( e.getStackTrace( ), e );
}
return StringUtils.EMPTY;
}
/**
* Default constructor
*/
public AppointmentJspBean( )
{
_nDefaultItemsPerPage = AppPropertiesService.getPropertyInt( PROPERTY_DEFAULT_LIST_APPOINTMENT_PER_PAGE, 10 );
}
private void cleanSession( HttpSession session )
{
_filter = null;
_strCurrentPageIndex = null;
_notValidatedAppointment = null;
_validatedAppointment = null;
AppointmentAsynchronousUploadHandler.getHandler( ).removeSessionFiles( session );
}
/**
* Clear uploaded files if needed.
*
* @param session
* The session of the current user
*/
private void clearUploadFilesIfNeeded( HttpSession session )
{
// If we do not reload an appointment, we clear uploaded files.
if ( _notValidatedAppointment == null && _validatedAppointment == null )
{
AppointmentAsynchronousUploadHandler.getHandler( ).removeSessionFiles( session );
}
}
/**
* Order the list of the appointment in the result tab with the order by and order asc given
*
* @param listAppointmentsDTO
* the llist of appointments
*/
private List<AppointmentDTO> orderList( List<AppointmentDTO> listAppointmentsDTO )
{
List<AppointmentDTO> sortedList = new ArrayList<>( );
if ( CollectionUtils.isNotEmpty( listAppointmentsDTO ) )
{
sortedList.addAll( listAppointmentsDTO );
}
Stream<AppointmentDTO> stream = null;
switch( _filter.getOrderBy( ) )
{
case LAST_NAME:
stream = sortedList.stream( ).sorted( ( a1, a2 ) -> a1.getLastName( ).compareTo( a2.getLastName( ) ) );
break;
case FIRST_NAME:
stream = sortedList.stream( ).sorted( ( a1, a2 ) -> a1.getFirstName( ).compareTo( a2.getFirstName( ) ) );
break;
case EMAIL:
stream = sortedList.stream( ).sorted( ( a1, a2 ) -> a1.getEmail( ).compareTo( a2.getEmail( ) ) );
break;
case PHONE_NUMBER:
// Added 'Comparator.nullsLast' to avoid NullPointerException when comparing null values (a user's phone number might be NULL in the database)
stream = sortedList.stream( ).sorted( Comparator.comparing( AppointmentDTO::getPhoneNumber, Comparator.nullsLast( Comparator.naturalOrder() ) ) );
break;
case NB_BOOKED_SEATS:
stream = sortedList.stream( ).sorted( ( a1, a2 ) -> Integer.compare( a1.getNbBookedSeats( ), a2.getNbBookedSeats( ) ) );
break;
case DATE_APPOINTMENT:
stream = sortedList.stream( ).sorted( ( a1, a2 ) -> a1.getStartingDateTime( ).compareTo( a2.getStartingDateTime( ) ) );
break;
case ADMIN:
stream = sortedList.stream( ).sorted( ( a1, a2 ) -> a1.getAdminUser( ).compareTo( a2.getAdminUser( ) ) );
break;
case STATUS:
stream = sortedList.stream( ).sorted( ( a1, a2 ) -> Boolean.compare( a1.getIsCancelled( ), a2.getIsCancelled( ) ) );
break;
default:
stream = sortedList.stream( ).sorted( ( a1, a2 ) -> a1.getStartingDateTime( ).compareTo( a2.getStartingDateTime( ) ) );
}
sortedList = stream.collect( Collectors.toList( ) );
if ( !_filter.isOrderAsc( ) )
{
Collections.reverse( sortedList );
}
return sortedList;
}
/**
* Get the URL to display the form of a workflow action. If the action has no form, then the user is redirected to the page to execute the workflow action
*
* @param request
* The request
* @param strIdAppointment
* The id of the appointment
* @param strIdAction
* The id of the workflow action
* @return The URL
*/
public static String getUrlExecuteWorkflowAction( HttpServletRequest request, String strIdAppointment, String strIdAction )
{
UrlItem url = new UrlItem( AppPathService.getBaseUrl( request ) + JSP_MANAGE_APPOINTMENTS );
url.addParameter( MVCUtils.PARAMETER_VIEW, VIEW_WORKFLOW_ACTION_FORM );
url.addParameter( PARAMETER_ID_APPOINTMENT, strIdAppointment );
url.addParameter( PARAMETER_ID_ACTION, strIdAction );
return url.getUrl( );
}
/**
* Get the workflow action form before processing the action. If the action does not need to display any form, then redirect the user to the workflow action
* processing page.
*
* @param request
* The request
* @return The HTML content to display, or the next URL to redirect the user to
*/
@View( VIEW_WORKFLOW_ACTION_FORM )
public synchronized String getWorkflowActionForm( HttpServletRequest request )
{
String strIdAction = request.getParameter( PARAMETER_ID_ACTION );
String strIdAppointment = request.getParameter( PARAMETER_ID_APPOINTMENT );
if ( StringUtils.isNotEmpty( strIdAction ) && StringUtils.isNumeric( strIdAction ) && StringUtils.isNotEmpty( strIdAppointment )
&& StringUtils.isNumeric( strIdAppointment ) )
{
int nIdAction = Integer.parseInt( strIdAction );
int nIdAppointment = Integer.parseInt( strIdAppointment );
if ( WorkflowService.getInstance( ).isDisplayTasksForm( nIdAction, getLocale( ) ) )
{
ITaskService taskService = SpringContextService.getBean( TaskService.BEAN_SERVICE );
List<ITask> listActionTasks = taskService.getListTaskByIdAction( nIdAction, getLocale( ) );
if ( listActionTasks.stream( ).anyMatch( task -> task.getTaskType( ).getKey( ).equals( "taskReportAppointment" ) )
/*
* && WorkflowService.getInstance( ).canProcessAction( nIdAppointment, Appointment.APPOINTMENT_RESOURCE_TYPE, nIdAction, nExternalParentId,
* request, false, null )
*/ )
{
AppointmentDTO appointment = AppointmentService.buildAppointmentDTOFromIdAppointment( nIdAppointment );
Map<String, String> additionalParameters = new HashMap<>( );
additionalParameters.put( PARAMETER_ID_APPOINTMENT, strIdAppointment );
additionalParameters.put( PARAMETER_NB_PLACE_TO_TAKE, String.valueOf( appointment.getNbBookedSeats( ) ) );
additionalParameters.put( PARAMETER_ID_FORM, String.valueOf( appointment.getIdForm( ) ) );
return redirect( request, VIEW_CALENDAR_MANAGE_APPOINTMENTS, additionalParameters );
}
String strHtmlTasksForm = WorkflowService.getInstance( ).getDisplayTasksForm( nIdAppointment, Appointment.APPOINTMENT_RESOURCE_TYPE, nIdAction,
request, getLocale( ), null );
Map<String, Object> model = new HashMap<>( );
model.put( MARK_TASKS_FORM, strHtmlTasksForm );
model.put( PARAMETER_ID_ACTION, nIdAction );
model.put( PARAMETER_ID_APPOINTMENT, nIdAppointment );
return getPage( PROPERTY_PAGE_TITLE_TASKS_FORM_WORKFLOW, TEMPLATE_TASKS_FORM_WORKFLOW, model );
}
return doProcessWorkflowAction( request );
}
return redirect( request, AppointmentFormJspBean.getURLManageAppointmentForms( request ) );
}
/**
* Do process a workflow action over an appointment
*
* @param request
* The request
* @return The next URL to redirect to
*/
@Action( ACTION_DO_PROCESS_WORKFLOW_ACTION )
public synchronized String doProcessWorkflowAction( HttpServletRequest request )
{
String strIdAction = request.getParameter( PARAMETER_ID_ACTION );
String strIdAppointment = request.getParameter( PARAMETER_ID_APPOINTMENT );
if ( StringUtils.isNotEmpty( strIdAction ) && StringUtils.isNumeric( strIdAction ) && StringUtils.isNotEmpty( strIdAppointment )
&& StringUtils.isNumeric( strIdAppointment ) )
{
int nIdAction = Integer.parseInt( strIdAction );
int nIdAppointment = Integer.parseInt( strIdAppointment );
Appointment appointment = AppointmentService.findAppointmentById( nIdAppointment );
List<AppointmentSlot> listApptSlot = appointment.getListAppointmentSlot( );
Slot slot = SlotService.findSlotById( listApptSlot.get( 0 ).getIdSlot( ) );
if ( request.getParameter( PARAMETER_BACK ) == null )
{
try
{
if ( WorkflowService.getInstance( ).isDisplayTasksForm( nIdAction, getLocale( ) ) )
{
String strError = WorkflowService.getInstance( ).doSaveTasksForm( nIdAppointment, Appointment.APPOINTMENT_RESOURCE_TYPE, nIdAction,
slot.getIdForm( ), request, getLocale( ), null );
if ( strError != null )
{
return redirect( request, strError );
}
}
else
{
ITaskService taskService = SpringContextService.getBean( TaskService.BEAN_SERVICE );
List<ITask> listActionTasks = taskService.getListTaskByIdAction( nIdAction, getLocale( ) );
for ( ITask task : listActionTasks )
{
if ( task.getTaskType( ).getKey( ).equals( "taskChangeAppointmentStatus" ) && ( appointment.getIsCancelled( ) ) )
{
for ( AppointmentSlot apptSlt : listApptSlot )
{
Slot slt = SlotService.findSlotById( apptSlt.getIdSlot( ) );
if ( apptSlt.getNbPlaces( ) > slt.getNbRemainingPlaces( ) )
{
return redirect( request,
AdminMessageService.getMessageUrl( request, MESSAGE_UNVAILABLE_SLOT, AdminMessage.TYPE_STOP ) );
}
}
}
}
WorkflowService.getInstance( ).doProcessAction( nIdAppointment, Appointment.APPOINTMENT_RESOURCE_TYPE, nIdAction, slot.getIdForm( ),
request, getLocale( ), false, null );
AppointmentListenerManager.notifyAppointmentWFActionTriggered( nIdAppointment, nIdAction );
}
}
catch( Exception e )
{
AppLogService.error( "Error Workflow", e );
}
Map<String, String> mapParams = new HashMap<>( );
mapParams.put( PARAMETER_ID_FORM, Integer.toString( slot.getIdForm( ) ) );
return redirect( request, VIEW_MANAGE_APPOINTMENTS, mapParams );
}
return redirect( request, VIEW_MANAGE_APPOINTMENTS, PARAMETER_ID_FORM, slot.getIdForm( ) );
}
return redirect( request, AppointmentFormJspBean.getURLManageAppointmentForms( request ) );
}
/**
* Do change the status of an appointment
*
* @param request
* The request
* @return The next URL to redirect to
* @throws AccessDeniedException
* If the user is not authorized to access this feature
*/
@Action( ACTION_DO_CHANGE_APPOINTMENT_STATUS )
public synchronized String doChangeAppointmentStatus( HttpServletRequest request ) throws AccessDeniedException
{
String strIdAppointment = request.getParameter( PARAMETER_ID_APPOINTMENT );
String strStatusCancelled = request.getParameter( PARAMETER_STATUS_CANCELLED );
if ( StringUtils.isNotEmpty( strIdAppointment ) && StringUtils.isNumeric( strIdAppointment ) && StringUtils.isNotEmpty( strStatusCancelled ) )
{
int nIdAppointment = Integer.parseInt( strIdAppointment );
boolean bStatusCancelled = Boolean.parseBoolean( strStatusCancelled );
Appointment appointment = AppointmentService.findAppointmentById( nIdAppointment );
int idSlot = appointment.getListAppointmentSlot( ).get( 0 ).getIdSlot( );
Slot slot = SlotService.findSlotById( idSlot );
if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, Integer.toString( slot.getIdForm( ) ),
AppointmentResourceIdService.PERMISSION_CHANGE_APPOINTMENT_STATUS, (User) getUser( ) ) )
{
throw new AccessDeniedException( AppointmentResourceIdService.PERMISSION_CHANGE_APPOINTMENT_STATUS );
}
if ( appointment.getIsCancelled( ) && !bStatusCancelled )
{
for ( AppointmentSlot apptSlot : appointment.getListAppointmentSlot( ) )
{
slot = SlotService.findSlotById( idSlot );
if ( ( apptSlot.getNbPlaces( ) > slot.getNbRemainingPlaces( ) ) )
{
return redirect( request, AdminMessageService.getMessageUrl( request, MESSAGE_UNVAILABLE_SLOT, AdminMessage.TYPE_STOP ) );
}
}
}
if ( appointment.getIsCancelled( ) != bStatusCancelled )
{
appointment.setIsCancelled( bStatusCancelled );
AppointmentService.updateAppointment( appointment );
AppLogService.info( LogUtilities.buildLog( ACTION_DO_CHANGE_APPOINTMENT_STATUS, strIdAppointment, getUser( ) ) );
}
return redirect( request, VIEW_MANAGE_APPOINTMENTS, PARAMETER_ID_FORM, slot.getIdForm( ) );
}
return redirect( request, AppointmentFormJspBean.getURLManageAppointmentForms( request ) );
}
/**
* List of all the available status of an appointment
*
* @return the list of the status
*/
private ReferenceList getListStatus( )
{
ReferenceList refListStatus = new ReferenceList( );
refListStatus.addItem( -1, StringUtils.EMPTY );
refListStatus.addItem( 0, I18nService.getLocalizedString( RESERVED, getLocale( ) ) );
refListStatus.addItem( 1, I18nService.getLocalizedString( UNRESERVED, getLocale( ) ) );
return refListStatus;
}
private List<AppointmentDTO> findListAppointmentsDTOByFilterByPage( )
{
int currentPage;
try
{
currentPage = Integer.parseInt( _strCurrentPageIndex );
}
catch( NumberFormatException ex )
{
currentPage = 1;
}
int skip = ( currentPage - 1 ) * _nItemsPerPage;
List<Integer> listIdAppointment = _filter.getListIdAppointment( );
_filter.setListIdAppointment( _listAppointmentsIds.stream( ).skip( skip ).limit( _nItemsPerPage ).collect( Collectors.toList( ) ) );
List<AppointmentDTO> listAppointmentsDTO = AppointmentService.findListAppointmentsDTOByFilter( _filter );
_filter.setListIdAppointment( listIdAppointment );
return listAppointmentsDTO;
}
}