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 fr.paris.lutece.api.user.User;
37  import fr.paris.lutece.plugins.appointment.business.appointment.Appointment;
38  import fr.paris.lutece.plugins.appointment.business.form.Form;
39  import fr.paris.lutece.plugins.appointment.business.planning.WeekDefinition;
40  import fr.paris.lutece.plugins.appointment.business.slot.Slot;
41  import fr.paris.lutece.plugins.appointment.modules.desk.service.AppointmentDeskService;
42  import fr.paris.lutece.plugins.appointment.modules.desk.util.IncrementSlot;
43  import fr.paris.lutece.plugins.appointment.modules.desk.util.IncrementingType;
44  import fr.paris.lutece.plugins.appointment.service.AppointmentResourceIdService;
45  import fr.paris.lutece.plugins.appointment.service.AppointmentService;
46  import fr.paris.lutece.plugins.appointment.service.AppointmentUtilities;
47  import fr.paris.lutece.plugins.appointment.service.CommentService;
48  import fr.paris.lutece.plugins.appointment.service.FormService;
49  import fr.paris.lutece.plugins.appointment.service.SlotService;
50  import fr.paris.lutece.plugins.appointment.service.WeekDefinitionService;
51  import fr.paris.lutece.plugins.appointment.web.AppointmentFormJspBean;
52  import fr.paris.lutece.plugins.appointment.web.dto.AppointmentFilterDTO;
53  import fr.paris.lutece.plugins.appointment.web.dto.AppointmentFormDTO;
54  import fr.paris.lutece.plugins.appointment.web.dto.CommentDTO;
55  import fr.paris.lutece.portal.service.util.AppLogService;
56  import fr.paris.lutece.portal.service.util.AppPropertiesService;
57  import fr.paris.lutece.portal.service.admin.AccessDeniedException;
58  import fr.paris.lutece.portal.service.i18n.I18nService;
59  import fr.paris.lutece.portal.service.mailinglist.AdminMailingListService;
60  import fr.paris.lutece.portal.service.plugin.Plugin;
61  import fr.paris.lutece.portal.service.plugin.PluginService;
62  import fr.paris.lutece.portal.service.rbac.RBACService;
63  import fr.paris.lutece.portal.util.mvc.admin.annotations.Controller;
64  import fr.paris.lutece.portal.util.mvc.commons.annotations.Action;
65  import fr.paris.lutece.portal.util.mvc.commons.annotations.View;
66  import fr.paris.lutece.util.ReferenceList;
67  import fr.paris.lutece.util.date.DateUtil;
68  import net.sf.json.JSONObject;
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         JSONObject json = new JSONObject( );
251         String strJson = request.getParameter( PARAMETER_DATA );
252         ObjectMapper mapper = new ObjectMapper( );
253         mapper.registerModule( new JavaTimeModule( ) );
254         mapper.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false );
255         AppLogService.debug( "appointmentDesk - Received strJson : " + strJson );
256 
257         List<Slot> listSlots;
258         try
259         {
260             listSlots = mapper.readValue( strJson, new TypeReference<List<Slot>>( )
261             {
262             } );
263 
264         }
265         catch( JsonProcessingException e )
266         {
267 
268             AppLogService.error( PROPERTY_MESSAGE_ERROR_PARSING_JSON + e.getMessage( ), e );
269             json.element( JSON_KEY_ERROR, I18nService.getLocalizedString( PROPERTY_MESSAGE_ERROR_PARSING_JSON, getLocale( ) ) );
270 
271             return json.toString( );
272         }
273 
274         if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, Integer.toString( listSlots.get( 0 ).getIdForm( ) ),
275                 AppointmentResourceIdService.PERMISSION_MODIFY_ADVANCED_SETTING_FORM, (User) getUser( ) ) )
276         {
277             AppLogService.error( AppointmentResourceIdService.PERMISSION_MODIFY_ADVANCED_SETTING_FORM,
278                     new AccessDeniedException( AppointmentResourceIdService.PERMISSION_MODIFY_ADVANCED_SETTING_FORM ) );
279             json.element( JSON_KEY_ERROR, I18nService.getLocalizedString( PROPERTY_MESSAGE_ERROR_ACCESS_DENIED, getLocale( ) ) );
280 
281             return json.toString( );
282         }
283 
284         AppointmentDeskService.closeAppointmentDesk( listSlots );
285 
286         json.element( JSON_KEY_SUCCESS, JSON_KEY_SUCCESS );
287         return json.toString( );
288 
289     }
290 
291     /**
292      * Process the change form of a appointmentdesk
293      *
294      * @param request
295      *            The Http request
296      * @return The Jsp URL of the process result
297      * @throws AccessDeniedException
298      * @throws JsonProcessingException
299      * @throws JsonMappingException
300      */
301     @Action( ACTION_OPEN_APPOINTMENTDESK )
302     public String doOpenAppointmentDesk( HttpServletRequest request )
303     {
304         JSONObject json = new JSONObject( );
305         String strJson = request.getParameter( PARAMETER_DATA );
306         AppLogService.debug( "appointmentDesk - Received strJson : " + strJson );
307         ObjectMapper mapper = new ObjectMapper( );
308         mapper.registerModule( new JavaTimeModule( ) );
309         mapper.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false );
310 
311         List<Slot> listSlots;
312         try
313         {
314 
315             listSlots = mapper.readValue( strJson, new TypeReference<List<Slot>>( )
316             {
317             } );
318 
319         }
320         catch( JsonProcessingException e )
321         {
322 
323             AppLogService.error( PROPERTY_MESSAGE_ERROR_PARSING_JSON + e.getMessage( ), e );
324             json.element( JSON_KEY_ERROR, I18nService.getLocalizedString( PROPERTY_MESSAGE_ERROR_PARSING_JSON, getLocale( ) ) );
325 
326             return json.toString( );
327         }
328 
329         if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, Integer.toString( listSlots.get( 0 ).getIdForm( ) ),
330                 AppointmentResourceIdService.PERMISSION_MODIFY_ADVANCED_SETTING_FORM, (User) getUser( ) ) )
331         {
332             AppLogService.error( AppointmentResourceIdService.PERMISSION_MODIFY_ADVANCED_SETTING_FORM,
333                     new AccessDeniedException( AppointmentResourceIdService.PERMISSION_MODIFY_ADVANCED_SETTING_FORM ) );
334             json.element( JSON_KEY_ERROR, I18nService.getLocalizedString( PROPERTY_MESSAGE_ERROR_ACCESS_DENIED, getLocale( ) ) );
335 
336             return json.toString( );
337 
338         }
339 
340         AppointmentDeskService.openAppointmentDesk( listSlots, _nMaxCapacity );
341 
342         json.element( JSON_KEY_SUCCESS, JSON_KEY_SUCCESS );
343         return json.toString( );
344 
345     }
346 
347     @Action( ACTION_INCREMENT_MAX_CAPACITY )
348     public String doIncrementMaxCapacity( HttpServletRequest request ) throws AccessDeniedException
349     {
350         IncrementSlottment/modules/desk/util/IncrementSlot.html#IncrementSlot">IncrementSlot incrementSlot = new IncrementSlot( );
351         String strIdForm = request.getParameter( PARAMETER_ID_FORM );
352         if ( !RBACService.isAuthorized( AppointmentFormDTO.RESOURCE_TYPE, strIdForm, AppointmentResourceIdService.PERMISSION_MODIFY_ADVANCED_SETTING_FORM,
353                 (User) getUser( ) ) )
354         {
355             throw new AccessDeniedException( AppointmentResourceIdService.PERMISSION_MODIFY_ADVANCED_SETTING_FORM );
356         }
357         populate( request, incrementSlot );
358 
359         AppointmentDeskService.incrementMaxCapacity( incrementSlot );
360 
361         return getManageAppointmentDesks( request );
362     }
363 
364     /**
365      * List of all the available type
366      * 
367      * @return the list of the type
368      */
369     private ReferenceList getListTypes( )
370     {
371         ReferenceList refListType = new ReferenceList( );
372         refListType.addItem( IncrementingType.FULLTIME.getValue( ), I18nService.getLocalizedString( IncrementingType.FULLTIME.getKey( ), getLocale( ) ) );
373         refListType.addItem( IncrementingType.HALFTIMEMORNING.getValue( ),
374                 I18nService.getLocalizedString( IncrementingType.HALFTIMEMORNING.getKey( ), getLocale( ) ) );
375         refListType.addItem( IncrementingType.HALFTIMEAFTERNOON.getValue( ),
376                 I18nService.getLocalizedString( IncrementingType.HALFTIMEAFTERNOON.getKey( ), getLocale( ) ) );
377         refListType.addItem( IncrementingType.LACE.getValue( ), I18nService.getLocalizedString( IncrementingType.LACE.getKey( ), getLocale( ) ) );
378 
379         return refListType;
380     }
381 
382     /**
383      * Populate a bean using parameters in http request
384      * 
385      * @param request
386      *            http request
387      * @param bean
388      *            bean to populate
389      */
390     private void populate( HttpServletRequest request, IncrementSlot incrementSlot )
391     {
392 
393         incrementSlot.setIdForm( Integer.parseInt( request.getParameter( PARAMETER_ID_FORM ) ) );
394         incrementSlot.setEndingTime( request.getParameter( PARAMETER_ENDING_TIME ) );
395         incrementSlot.setStartingTime( request.getParameter( PARAMETER_STARTING_TIME ) );
396         incrementSlot.setIncrementingValue( Integer.parseInt( request.getParameter( PARAMETER_INCREMENTING_VALUE ) ) );
397         incrementSlot.setEndingDate( DateUtil.formatDate( request.getParameter( PARAMETER_ENDING_DATE ), getLocale( ) ).toInstant( )
398                 .atZone( ZoneId.systemDefault( ) ).toLocalDate( ) );
399 
400         incrementSlot.setStartingDate( DateUtil.formatDate( request.getParameter( PARAMETER_STARTING_DATE ), getLocale( ) ).toInstant( )
401                 .atZone( ZoneId.systemDefault( ) ).toLocalDate( ) );
402 
403         int type = Integer.parseInt( request.getParameter( PARAMETER_TYPE ) );
404         incrementSlot.setType( IncrementingType.valueOf( type ) );
405     }
406 }