View Javadoc
1   /*
2    * Copyright (c) 2002-2022, City of Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  package fr.paris.lutece.plugins.appointment.modules.desk.web;
35  
36  import com.fasterxml.jackson.databind.node.ObjectNode;
37  import fr.paris.lutece.api.user.User;
38  import fr.paris.lutece.plugins.appointment.business.appointment.Appointment;
39  import fr.paris.lutece.plugins.appointment.business.form.Form;
40  import fr.paris.lutece.plugins.appointment.business.planning.WeekDefinition;
41  import fr.paris.lutece.plugins.appointment.business.slot.Slot;
42  import fr.paris.lutece.plugins.appointment.modules.desk.service.AppointmentDeskService;
43  import fr.paris.lutece.plugins.appointment.modules.desk.util.IncrementSlot;
44  import fr.paris.lutece.plugins.appointment.modules.desk.util.IncrementingType;
45  import fr.paris.lutece.plugins.appointment.service.AppointmentResourceIdService;
46  import fr.paris.lutece.plugins.appointment.service.AppointmentService;
47  import fr.paris.lutece.plugins.appointment.service.AppointmentUtilities;
48  import fr.paris.lutece.plugins.appointment.service.CommentService;
49  import fr.paris.lutece.plugins.appointment.service.FormService;
50  import fr.paris.lutece.plugins.appointment.service.SlotService;
51  import fr.paris.lutece.plugins.appointment.service.WeekDefinitionService;
52  import fr.paris.lutece.plugins.appointment.web.AppointmentFormJspBean;
53  import fr.paris.lutece.plugins.appointment.web.dto.AppointmentFilterDTO;
54  import fr.paris.lutece.plugins.appointment.web.dto.AppointmentFormDTO;
55  import fr.paris.lutece.plugins.appointment.web.dto.CommentDTO;
56  import fr.paris.lutece.portal.service.util.AppLogService;
57  import fr.paris.lutece.portal.service.util.AppPropertiesService;
58  import fr.paris.lutece.portal.service.admin.AccessDeniedException;
59  import fr.paris.lutece.portal.service.i18n.I18nService;
60  import fr.paris.lutece.portal.service.mailinglist.AdminMailingListService;
61  import fr.paris.lutece.portal.service.plugin.Plugin;
62  import fr.paris.lutece.portal.service.plugin.PluginService;
63  import fr.paris.lutece.portal.service.rbac.RBACService;
64  import fr.paris.lutece.portal.util.mvc.admin.annotations.Controller;
65  import fr.paris.lutece.portal.util.mvc.commons.annotations.Action;
66  import fr.paris.lutece.portal.util.mvc.commons.annotations.View;
67  import fr.paris.lutece.util.ReferenceList;
68  import fr.paris.lutece.util.date.DateUtil;
69  
70  import java.time.LocalDate;
71  import java.time.ZoneId;
72  import java.util.Comparator;
73  import java.util.Date;
74  import java.util.HashMap;
75  import java.util.List;
76  import java.util.Map;
77  import java.util.NoSuchElementException;
78  
79  import javax.servlet.http.HttpServletRequest;
80  
81  import org.apache.commons.lang3.StringUtils;
82  
83  import com.fasterxml.jackson.core.JsonProcessingException;
84  import com.fasterxml.jackson.core.type.TypeReference;
85  import com.fasterxml.jackson.databind.DeserializationFeature;
86  import com.fasterxml.jackson.databind.JsonMappingException;
87  import com.fasterxml.jackson.databind.ObjectMapper;
88  import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
89  
90  /**
91   * This class provides the user interface to manage AppointmentDesk features ( manage, create, modify, remove )
92   */
93  @Controller( controllerJsp = "ManageAppointmentDesks.jsp", controllerPath = "jsp/admin/plugins/appointment/modules/desk/", right = AppointmentFormJspBean.RIGHT_MANAGEAPPOINTMENTFORM )
94  public class AppointmentDeskJspBean extends AbstractManageAppointmentDeskJspBean
95  {
96      /**
97       * 
98       */
99      private static final long serialVersionUID = -2761497602249048780L;
100 
101     // Templates
102     private static final String TEMPLATE_MANAGE_APPOINTMENTDESKS = "/admin/plugins/appointment/modules/desk/manage_appointmentdesks.html";
103 
104     // Parameters
105     private static final String PARAMETER_ID_FORM = "id_form";
106     private static final String PARAMETER_CONTEXT = "context";
107     private static final String PARAMETER_NUMB_DESK = "numb_desk";
108     private static final String PARAMETER_DATE_DAY = "day";
109     private static final String PARAMETER_DATA = "data";
110 
111     private static final String PARAMETER_ENDING_DATE = "ending_date";
112     private static final String PARAMETER_STARTING_DATE = "starting_date";
113     private static final String PARAMETER_STARTING_TIME = "starting_time";
114     private static final String PARAMETER_ENDING_TIME = "ending_time";
115     private static final String PARAMETER_INCREMENTING_VALUE = "incrementing_value";
116     private static final String PARAMETER_TYPE = "type";
117     // Properties for page titles
118     private static final String PROPERTY_PAGE_TITLE_MANAGE_APPOINTMENTDESKS = "appointment-desk.manage_appointmentdesks.pageTitle";
119 
120     // Markers
121     private static final String MARK_LOCALE = "language";
122     private static final String MARK_MACRO_LOCALE = "locale";
123     private static final String MARK_DATE_DAY = "day";
124     private static final String MARK_ID_FORM = "idForm";
125     private static final String MARK_LIST_COMMENTS = "list_comments";
126     private static final String MARK_LIST_SLOT = "list_slot";
127     private static final String MARK_LIST_APPOINTMENT = "list_appointment";
128     private static final String MARK_LIST_TYPE = "list_types";
129     private static final String MARK_FORM = "appointmentForm";
130     private static final String MARK_ACTIVATE_EDIT_MODE = "activateEditMode";
131     private static final String MARK_MAILING_LIST = "mailing_list";
132     private static final String MARK_CONTEXT = "context";
133     private static final String MARK_APPOINTMENT_DESK_ENABLED = "isDeskInstalled";
134 
135     // Properties
136 
137     // Validations
138 
139     // Views
140     private static final String VIEW_MANAGE_APPOINTMENTDESKS = "manageAppointmentDesks";
141 
142     // Actions
143     private static final String ACTION_CLOSE_APPOINTMENTDESK = "closeAppointmentDesk";
144     private static final String ACTION_OPEN_APPOINTMENTDESK = "openAppointmentDesk";
145     private static final String ACTION_INCREMENT_MAX_CAPACITY = "incrementMaxCapacity";
146 
147     // Infos
148     private static final String JSON_KEY_ERROR = "error";
149     private static final String JSON_KEY_SUCCESS = "success";
150 
151     private static final String PROPERTY_MESSAGE_ERROR_PARSING_JSON = "module.appointment.desk.error.parsing.json";
152     private static final String PROPERTY_MESSAGE_ERROR_ACCESS_DENIED = "module.appointment.desk.error.access.denied";
153     // Session variable to store working values
154     private int _nMaxCapacity;
155     private String _strContext;
156 
157     /**
158      * Build the Manage View
159      * 
160      * @param request
161      *            The HTTP request
162      * @return The page
163      */
164     @View( value = VIEW_MANAGE_APPOINTMENTDESKS, defaultView = true )
165     public String getManageAppointmentDesks( HttpServletRequest request )
166     {
167         Plugin moduleAppointmentDesk = getPlugin( );
168         String strIdForm = request.getParameter( PARAMETER_ID_FORM );
169         int nIdForm = Integer.parseInt( strIdForm );
170         String strDayDate = request.getParameter( PARAMETER_DATE_DAY );
171         String strContext = request.getParameter( PARAMETER_CONTEXT );
172         _strContext = ( StringUtils.isNotEmpty( strContext ) ) ? strContext : _strContext;
173         boolean activateEditMode = true;
174         LocalDate dateDay = null;
175         User user = getUser( );
176         if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm, AppointmentResourceIdService.PERMISSION_MODIFY_ADVANCED_SETTING_FORM,
177                 user ) )
178         {
179             activateEditMode = false;
180         }
181         Form form = FormService.findFormLightByPrimaryKey( nIdForm );
182         HashMap<LocalDate, WeekDefinition> mapWeekDefinition = WeekDefinitionService.findAllWeekDefinition( nIdForm );
183         if ( StringUtils.isNotEmpty( strDayDate ) )
184         {
185             Date dateofDay = DateUtil.formatDate( strDayDate, getLocale( ) );
186             dateDay = dateofDay.toInstant( ).atZone( ZoneId.systemDefault( ) ).toLocalDate( );
187         }
188         else
189         {
190             dateDay = LocalDate.now( );
191             strDayDate = DateUtil.getDateString( Date.from( dateDay.atStartOfDay( ).atZone( ZoneId.systemDefault( ) ).toInstant( ) ), getLocale( ) );
192         }
193         int appointmentDesk = 0;
194         List<Slot> listSlot = SlotService.buildListSlot( nIdForm, mapWeekDefinition, dateDay, dateDay );
195         if ( !listSlot.isEmpty( ) )
196         {
197 
198             Slot slot = listSlot.stream( ).max( Comparator.comparing( Slot::getMaxCapacity ) ).orElseThrow( NoSuchElementException::new );
199             appointmentDesk = slot.getMaxCapacity( );
200 
201         }
202         Map<String, Object> model = getModel( );
203         java.sql.Date dateSqlDaey = java.sql.Date.valueOf( dateDay );
204         List<CommentDTO> listComment = CommentService.buildCommentDTO( CommentService.findListCommentsInclusive( dateSqlDaey, dateSqlDaey, nIdForm ) );
205 
206         AppointmentFilterDTO filter = new AppointmentFilterDTO( );
207         filter.setIdForm( nIdForm );
208         filter.setStartingDateOfSearch( java.sql.Date.valueOf( dateDay ) );
209         filter.setEndingDateOfSearch( java.sql.Date.valueOf( dateDay ) );
210         filter.setStatus( 0 );
211         List<Appointment> listAppt = AppointmentService.findListAppointmentsByFilter( filter );
212         _nMaxCapacity = appointmentDesk;
213 
214         model.put( MARK_ACTIVATE_EDIT_MODE, activateEditMode );
215         model.put( MARK_CONTEXT, _strContext );
216         model.put( MARK_LIST_COMMENTS, listComment );
217         model.put( PARAMETER_NUMB_DESK, appointmentDesk );
218         model.put( MARK_LIST_SLOT, listSlot );
219         model.put( MARK_LIST_APPOINTMENT, listAppt );
220         model.put( MARK_LOCALE, getLocale( ) );
221         model.put( MARK_DATE_DAY, strDayDate );
222         model.put( MARK_ID_FORM, nIdForm );
223         model.put( MARK_FORM, form );
224         model.put( MARK_MACRO_LOCALE, getLocale( ) );
225         model.put( MARK_LIST_TYPE, getListTypes( ) );
226         model.put( MARK_MAILING_LIST, AdminMailingListService.getMailingLists( getUser( ) ) );
227         model.put( AppointmentUtilities.MARK_PERMISSION_ADD_COMMENT, String.valueOf(
228                 RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm, AppointmentResourceIdService.PERMISSION_ADD_COMMENT_FORM, user ) ) );
229         model.put( AppointmentUtilities.MARK_PERMISSION_MODERATE_COMMENT, String.valueOf( RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm,
230                 AppointmentResourceIdService.PERMISSION_MODERATE_COMMENT_FORM, user ) ) );
231         model.put( AppointmentUtilities.MARK_PERMISSION_ACCESS_CODE, user.getAccessCode( ) );
232         model.put( MARK_APPOINTMENT_DESK_ENABLED, ( moduleAppointmentDesk != null ) && moduleAppointmentDesk.isInstalled( ) );
233 
234         return getPage( PROPERTY_PAGE_TITLE_MANAGE_APPOINTMENTDESKS, TEMPLATE_MANAGE_APPOINTMENTDESKS, model );
235     }
236 
237     /**
238      * Process the data capture form of a new appointmentdesk
239      *
240      * @param request
241      *            The Http Request
242      * @return The Jsp URL of the process result
243      * @throws AccessDeniedException
244      * @throws JsonProcessingException
245      * @throws JsonMappingException
246      */
247     @Action( ACTION_CLOSE_APPOINTMENTDESK )
248     public String docloseAppointmentDesk( HttpServletRequest request )
249     {
250         ObjectMapper mapper = new ObjectMapper( );
251         mapper.registerModule( new JavaTimeModule( ) );
252         mapper.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false );
253 
254         ObjectNode json = mapper.createObjectNode();
255         String strJson = request.getParameter(PARAMETER_DATA);
256         AppLogService.debug( "appointmentDesk - Received strJson : " + strJson );
257 
258         List<Slot> listSlots;
259         try
260         {
261             listSlots = mapper.readValue( strJson, new TypeReference<List<Slot>>( )
262             {
263             } );
264 
265         }
266         catch( JsonProcessingException e )
267         {
268 
269             AppLogService.error( PROPERTY_MESSAGE_ERROR_PARSING_JSON + e.getMessage( ), e );
270             json.put( JSON_KEY_ERROR, I18nService.getLocalizedString( PROPERTY_MESSAGE_ERROR_PARSING_JSON, getLocale( ) ) );
271 
272             return json.toString( );
273         }
274 
275         if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, Integer.toString( listSlots.get( 0 ).getIdForm( ) ),
276                 AppointmentResourceIdService.PERMISSION_MODIFY_ADVANCED_SETTING_FORM, (User) getUser( ) ) )
277         {
278             AppLogService.error( AppointmentResourceIdService.PERMISSION_MODIFY_ADVANCED_SETTING_FORM,
279                     new AccessDeniedException( AppointmentResourceIdService.PERMISSION_MODIFY_ADVANCED_SETTING_FORM ) );
280             json.put( JSON_KEY_ERROR, I18nService.getLocalizedString( PROPERTY_MESSAGE_ERROR_ACCESS_DENIED, getLocale( ) ) );
281 
282             return json.toString( );
283         }
284 
285         AppointmentDeskService.closeAppointmentDesk( listSlots );
286 
287         json.put( JSON_KEY_SUCCESS, JSON_KEY_SUCCESS );
288         return json.toString( );
289 
290     }
291 
292     /**
293      * Process the change form of a appointmentdesk
294      *
295      * @param request
296      *            The Http request
297      * @return The Jsp URL of the process result
298      * @throws AccessDeniedException
299      * @throws JsonProcessingException
300      * @throws JsonMappingException
301      */
302     @Action( ACTION_OPEN_APPOINTMENTDESK )
303     public String doOpenAppointmentDesk( HttpServletRequest request )
304     {
305         ObjectMapper mapper = new ObjectMapper( );
306         mapper.registerModule( new JavaTimeModule( ) );
307         mapper.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false );
308 
309         ObjectNode json = mapper.createObjectNode();
310         String strJson = request.getParameter(PARAMETER_DATA);
311         AppLogService.debug( "appointmentDesk - Received strJson : " + strJson );
312 
313         List<Slot> listSlots;
314         try
315         {
316 
317             listSlots = mapper.readValue( strJson, new TypeReference<List<Slot>>( )
318             {
319             } );
320 
321         }
322         catch( JsonProcessingException e )
323         {
324 
325             AppLogService.error( PROPERTY_MESSAGE_ERROR_PARSING_JSON + e.getMessage( ), e );
326             json.put( JSON_KEY_ERROR, I18nService.getLocalizedString( PROPERTY_MESSAGE_ERROR_PARSING_JSON, getLocale( ) ) );
327 
328             return json.toString( );
329         }
330 
331         if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, Integer.toString( listSlots.get( 0 ).getIdForm( ) ),
332                 AppointmentResourceIdService.PERMISSION_MODIFY_ADVANCED_SETTING_FORM, (User) getUser( ) ) )
333         {
334             AppLogService.error( AppointmentResourceIdService.PERMISSION_MODIFY_ADVANCED_SETTING_FORM,
335                     new AccessDeniedException( AppointmentResourceIdService.PERMISSION_MODIFY_ADVANCED_SETTING_FORM ) );
336             json.put( JSON_KEY_ERROR, I18nService.getLocalizedString( PROPERTY_MESSAGE_ERROR_ACCESS_DENIED, getLocale( ) ) );
337 
338             return json.toString( );
339 
340         }
341 
342         AppointmentDeskService.openAppointmentDesk( listSlots, _nMaxCapacity );
343 
344         json.put( JSON_KEY_SUCCESS, JSON_KEY_SUCCESS );
345         return json.toString( );
346 
347     }
348 
349     @Action( ACTION_INCREMENT_MAX_CAPACITY )
350     public String doIncrementMaxCapacity( HttpServletRequest request ) throws AccessDeniedException
351     {
352         IncrementSlottment/modules/desk/util/IncrementSlot.html#IncrementSlot">IncrementSlot incrementSlot = new IncrementSlot( );
353         String strIdForm = request.getParameter( PARAMETER_ID_FORM );
354         if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm, AppointmentResourceIdService.PERMISSION_MODIFY_ADVANCED_SETTING_FORM,
355                 (User) getUser( ) ) )
356         {
357             throw new AccessDeniedException( AppointmentResourceIdService.PERMISSION_MODIFY_ADVANCED_SETTING_FORM );
358         }
359         populate( request, incrementSlot );
360 
361         AppointmentDeskService.incrementMaxCapacity( incrementSlot );
362 
363         return getManageAppointmentDesks( request );
364     }
365 
366     /**
367      * List of all the available type
368      * 
369      * @return the list of the type
370      */
371     private ReferenceList getListTypes( )
372     {
373         ReferenceList refListType = new ReferenceList( );
374         refListType.addItem( IncrementingType.FULLTIME.getValue( ), I18nService.getLocalizedString( IncrementingType.FULLTIME.getKey( ), getLocale( ) ) );
375         refListType.addItem( IncrementingType.HALFTIMEMORNING.getValue( ),
376                 I18nService.getLocalizedString( IncrementingType.HALFTIMEMORNING.getKey( ), getLocale( ) ) );
377         refListType.addItem( IncrementingType.HALFTIMEAFTERNOON.getValue( ),
378                 I18nService.getLocalizedString( IncrementingType.HALFTIMEAFTERNOON.getKey( ), getLocale( ) ) );
379         refListType.addItem( IncrementingType.LACE.getValue( ), I18nService.getLocalizedString( IncrementingType.LACE.getKey( ), getLocale( ) ) );
380 
381         return refListType;
382     }
383 
384     /**
385      * Populate a bean using parameters in http request
386      * 
387      * @param request
388      *            http request
389      * @param bean
390      *            bean to populate
391      */
392     private void populate( HttpServletRequest request, IncrementSlot incrementSlot )
393     {
394 
395         incrementSlot.setIdForm( Integer.parseInt( request.getParameter( PARAMETER_ID_FORM ) ) );
396         incrementSlot.setEndingTime( request.getParameter( PARAMETER_ENDING_TIME ) );
397         incrementSlot.setStartingTime( request.getParameter( PARAMETER_STARTING_TIME ) );
398         incrementSlot.setIncrementingValue( Integer.parseInt( request.getParameter( PARAMETER_INCREMENTING_VALUE ) ) );
399         incrementSlot.setEndingDate( DateUtil.formatDate( request.getParameter( PARAMETER_ENDING_DATE ), getLocale( ) ).toInstant( )
400                 .atZone( ZoneId.systemDefault( ) ).toLocalDate( ) );
401 
402         incrementSlot.setStartingDate( DateUtil.formatDate( request.getParameter( PARAMETER_STARTING_DATE ), getLocale( ) ).toInstant( )
403                 .atZone( ZoneId.systemDefault( ) ).toLocalDate( ) );
404 
405         int type = Integer.parseInt( request.getParameter( PARAMETER_TYPE ) );
406         incrementSlot.setType( IncrementingType.valueOf( type ) );
407     }
408 }