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.dansmarue.modules.rest.xpage.signalement;
35  
36  import java.util.ArrayList;
37  import java.util.HashMap;
38  import java.util.List;
39  import java.util.Map;
40  
41  import javax.inject.Inject;
42  import javax.inject.Named;
43  import javax.servlet.http.HttpServletRequest;
44  
45  import fr.paris.lutece.plugins.dansmarue.utils.IListUtils;
46  import org.apache.commons.collections.CollectionUtils;
47  import org.apache.commons.fileupload.FileItem;
48  import org.apache.commons.lang.ArrayUtils;
49  import org.apache.commons.lang.StringUtils;
50  
51  import fr.paris.lutece.plugins.dansmarue.business.entities.NotificationSignalementUserMultiContents;
52  import fr.paris.lutece.plugins.dansmarue.business.entities.ObservationRejet;
53  import fr.paris.lutece.plugins.dansmarue.business.entities.Signalement;
54  import fr.paris.lutece.plugins.dansmarue.business.entities.TypeSignalement;
55  import fr.paris.lutece.plugins.dansmarue.modules.rest.service.ManageSignalementService;
56  import fr.paris.lutece.plugins.dansmarue.modules.rest.service.upload.handler.DansMaRueUploadHandler;
57  import fr.paris.lutece.plugins.dansmarue.service.IObservationRejetService;
58  import fr.paris.lutece.plugins.dansmarue.service.ISignalementService;
59  import fr.paris.lutece.plugins.dansmarue.service.ITypeSignalementService;
60  import fr.paris.lutece.plugins.dansmarue.service.IWorkflowService;
61  import fr.paris.lutece.plugins.dansmarue.utils.impl.ListUtils;
62  import fr.paris.lutece.plugins.workflowcore.business.state.State;
63  import fr.paris.lutece.plugins.workflowcore.service.action.IActionService;
64  import fr.paris.lutece.plugins.workflowcore.service.state.IStateService;
65  import fr.paris.lutece.plugins.workflowcore.service.task.ITaskService;
66  import fr.paris.lutece.portal.service.i18n.I18nService;
67  import fr.paris.lutece.portal.service.plugin.Plugin;
68  import fr.paris.lutece.portal.service.spring.SpringContextService;
69  import fr.paris.lutece.portal.service.template.AppTemplateService;
70  import fr.paris.lutece.portal.service.util.AppLogService;
71  import fr.paris.lutece.portal.service.util.AppPropertiesService;
72  import fr.paris.lutece.portal.service.workflow.WorkflowService;
73  import fr.paris.lutece.portal.web.xpages.XPage;
74  import fr.paris.lutece.portal.web.xpages.XPageApplication;
75  import fr.paris.lutece.util.ReferenceList;
76  import fr.paris.lutece.util.html.HtmlTemplate;
77  import fr.paris.lutece.util.url.UrlItem;
78  
79  /**
80   * the XPage app to manage signalement without Web Service.
81   */
82  public class ManageSignalementApp implements XPageApplication
83  {
84  
85      /** The Constant serialVersionUID. */
86      private static final long serialVersionUID = 4838342837767932281L;
87  
88      /** The Constant PROPERTY_BASE_URL. */
89      // PROPERTIES
90      private static final String PROPERTY_BASE_URL = "lutece.prod.url";
91  
92      /** The Constant JSP_PORTAL. */
93      // JSP
94      private static final String JSP_PORTAL = "jsp/site/Portal.jsp";
95  
96      /** The Constant TEMPLATE_ACTIONS. */
97      private static final String TEMPLATE_ACTIONS = "skin/plugins/signalement/modules/rest/managewithoutws/manage_actions.html";
98  
99      /** The Constant MARK_LOCALE. */
100     private static final String MARK_LOCALE = "locale";
101 
102     /** The Constant MARK_MOTIFS. */
103     private static final String MARK_MOTIFS = "motifs";
104 
105     /** The Constant MARK_ID. */
106     private static final String MARK_ID = "id";
107 
108     /** The Constant MARK_ACTION. */
109     private static final String MARK_ACTION = "action";
110 
111     /** The Constant MARK_TYPE_LIST. */
112     private static final String MARK_TYPE_LIST = "type_list";
113 
114     /** The Constant MARK_TYPE. */
115     private static final String MARK_TYPE = "type";
116 
117     /** The Constant MARK_ERROR. */
118     private static final String MARK_ERROR = "error";
119 
120     /** The Constant MARK_HAS_EMAIL_SIGNALEUR. */
121     private static final String MARK_HAS_EMAIL_SIGNALEUR = "has_email_signaleur";
122 
123     /** The Constant PARAMETER_PAGE. */
124     private static final String PARAMETER_PAGE = "page";
125 
126     /** The Constant PARAMETER_SUIVI. */
127     private static final String PARAMETER_SUIVI = "suivi";
128 
129     /** The Constant PARAMETER_TOKEN. */
130     private static final String PARAMETER_TOKEN = "token";
131 
132     /** The Constant PARAMETER_MOTIF_REJET. */
133     private static final String PARAMETER_MOTIF_REJET = "motif_rejet";
134 
135     /** The Constant PARAMETER_MOTIF_AUTRE_CHECKBOX. */
136     private static final String PARAMETER_MOTIF_AUTRE_CHECKBOX = "motif_autre_checkbox";
137 
138     /** The Constant PARAMETER_MOTIF_AUTRE. */
139     private static final String PARAMETER_MOTIF_AUTRE = "motif_autre";
140 
141     /** The Constant PARAMETER_ID_TYPE_ANOMALIE. */
142     private static final String PARAMETER_ID_TYPE_ANOMALIE = "typeSignalementSelect";
143 
144     /** The Constant PARAMETER_PHOTO_DONE. */
145     private static final String PARAMETER_PHOTO_DONE = "photoDone";
146 
147     /** The Constant PARAMETER_CHOSEN_MESSAGE. */
148     private static final String PARAMETER_CHOSEN_MESSAGE = "chosenMessage";
149 
150     /** The Constant I18N_ERROR_MOTIF_REJET. */
151     private static final String I18N_ERROR_MOTIF_REJET = "module.dansmarue.rest.manage.signalement.error.motif.rejet";
152 
153     /** The Constant I18N_ERROR_PROGRAMMATION_DATE. */
154     private static final String I18N_ERROR_PROGRAMMATION_DATE = "module.dansmarue.rest.manage.signalement.error.programmation.date";
155 
156     /** The Constant I18N_ERROR_TYPE_ANOMALIE. */
157     private static final String I18N_ERROR_TYPE_ANOMALIE = "module.dansmarue.rest.manage.signalement.error.type.anomalie";
158 
159     /** The Constant I18N_ERROR_NO_SIGNALEMENT. */
160     private static final String I18N_ERROR_NO_SIGNALEMENT = "module.dansmarue.rest.manage.signalement.error.no.signalement";
161 
162     /** The Constant I18N_ERROR_MANDATORY_ACTION. */
163     private static final String I18N_ERROR_MANDATORY_ACTION = "module.dansmarue.rest.manage.signalement.actions.aide";
164 
165     /** The Constant I18N_TITLE. */
166     private static final String I18N_TITLE = "module.dansmarue.rest.manage.signalement.gestion.title";
167 
168     /** The Constant I18N_SUCCESS. */
169     private static final String I18N_SUCCESS = "module.dansmarue.rest.manage.signalement.success";
170 
171     /** The signalement service. */
172     private transient ISignalementService _signalementService = SpringContextService.getBean( "signalementService" );
173 
174     /** The observation rejet service. */
175     private transient IObservationRejetService _observationRejetService = SpringContextService.getBean( "observationRejetService" );
176 
177     /** The manage signalement service. */
178     private transient ManageSignalementService _manageSignalementService = SpringContextService.getBean( "signalement-rest.manageSignalementService" );
179 
180     /** The type signalement service. */
181     private transient ITypeSignalementService _typeSignalementService = SpringContextService.getBean( "typeSignalementService" );
182 
183     /** The signalement workflow service. */
184     private transient IWorkflowService _signalementWorkflowService = SpringContextService.getBean( "signalement.workflowService" );
185 
186     /** The dansmarue upload handler. */
187     private transient DansMaRueUploadHandler _dansmarueUploadHandler = SpringContextService.getBean( "signalement-rest.dansmarueUploadHandler" );
188 
189     /** The task service. */
190     @Inject
191     private ITaskService _taskService;
192 
193     /** The action service. */
194     @Inject
195     private IActionService _actionService;
196 
197     /** The state service. */
198     @Inject
199     private IStateService _stateService;
200 
201     /** The date utils. */
202     // UTILS
203     private transient IListUtils _listUtils = SpringContextService.getBean( "signalement.listUtils" );
204 
205     /**
206      * {@inheritDoc}
207      */
208     @SuppressWarnings( "deprecation" )
209     @Override
210     public XPage getPage( HttpServletRequest request, int nMode, Plugin plugin )
211     {
212         XPage page = new XPage( );
213         Map<String, Object> model = new HashMap<>( );
214         model.put( MARK_LOCALE, request.getLocale( ) );
215 
216         WorkflowService workflowService = WorkflowService.getInstance( );
217         String action = getAction( request );
218         Signalement bean = getSignalement( request );
219         Integer workflowId = _signalementWorkflowService.getSignalementWorkflowId( );
220 
221         State state = null;
222         if ( bean != null )
223         {
224             state = workflowService.getState( bean.getId( ).intValue( ), Signalement.WORKFLOW_RESOURCE_TYPE, workflowId, null );
225             model.put( "state", state );
226         }
227 
228         // if blank, only display the choice page
229         if ( StringUtils.isBlank( action ) && ( bean != null ) )
230         {
231             addMotifs( model );
232             addTypeAnomalie( model, bean );
233             model.put( "signalement", bean );
234 
235             boolean hasEmailSignaleur = false;
236             if ( CollectionUtils.isNotEmpty( bean.getSignaleurs( ) ) && !StringUtils.isBlank( bean.getSignaleurs( ).get( 0 ).getMail( ) ) )
237             {
238                 hasEmailSignaleur = true;
239             }
240             model.put( MARK_HAS_EMAIL_SIGNALEUR, hasEmailSignaleur );
241 
242         }
243         // else, validate or not the action
244         else
245             if ( bean != null )
246             {
247                 String error = validateForm( request );
248                 if ( StringUtils.isBlank( error ) )
249                 {
250                     // Vidage du motif autre si checkbox non cochée
251                     boolean motifAutreCheckbox = StringUtils.isNotBlank( request.getParameter( PARAMETER_MOTIF_AUTRE_CHECKBOX ) );
252                     String motifAutre = StringUtils.EMPTY;
253                     if ( motifAutreCheckbox )
254                     {
255                         motifAutre = request.getParameter( PARAMETER_MOTIF_AUTRE );
256                     }
257 
258                     String stridTypeAnomalie = request.getParameter( PARAMETER_ID_TYPE_ANOMALIE );
259                     long idTypeAnomalie = StringUtils.isNotBlank( stridTypeAnomalie ) ? Long.parseLong( stridTypeAnomalie ) : -1;
260 
261                     FileItem imageFile = _dansmarueUploadHandler.getFile( request, PARAMETER_PHOTO_DONE );
262 
263                     request.getSession( ).setAttribute( PARAMETER_CHOSEN_MESSAGE, request.getParameter( PARAMETER_CHOSEN_MESSAGE ) );
264 
265                     error = _manageSignalementService.processAction( request, action, bean, request.getParameter( "commentaires" ),
266                             request.getParameterValues( PARAMETER_MOTIF_REJET ), motifAutre, request.getParameter( "dateProgrammation" ), idTypeAnomalie,
267                             imageFile );
268                     if ( StringUtils.isNotBlank( error ) )
269                     {
270                         model.put( MARK_ERROR, error );
271                     }
272                     else
273                     {
274                         if ( _dansmarueUploadHandler.hasFile( request, PARAMETER_PHOTO_DONE ) )
275                         {
276                             _dansmarueUploadHandler.removeFileItem( PARAMETER_PHOTO_DONE, request.getSession( ), 0 );
277                         }
278 
279                         UrlItem urlItem;
280 
281                         urlItem = new UrlItem( AppPropertiesService.getProperty( PROPERTY_BASE_URL ) + JSP_PORTAL );
282 
283                         urlItem.addParameter( PARAMETER_PAGE, PARAMETER_SUIVI );
284                         urlItem.addParameter( PARAMETER_TOKEN, bean.getToken( ) );
285 
286                         String link = "<a href=\"" + urlItem.getUrl( ) + "\" >LIEN_CONSULTATION</a>";
287                         model.put( "success", I18nService.getLocalizedString( I18N_SUCCESS, new String [ ] {
288                                 link
289                         }, request.getLocale( ) ) );
290                     }
291                 }
292                 else
293                 {
294                     model.put( MARK_ERROR, error );
295                 }
296             }
297             else
298             {
299                 model.put( MARK_ERROR, I18nService.getLocalizedString( I18N_ERROR_NO_SIGNALEMENT, request.getLocale( ) ) );
300             }
301 
302         // Récupération des messages de service fait
303         Map<Integer, List<NotificationSignalementUserMultiContents>> allMessagesServiceFait = _signalementWorkflowService
304                 .selectMessageServiceFaitPresta( action );
305 
306         if ( ( state != null ) && ( state.getId( ) == AppPropertiesService.getPropertyInt( "signalement.idStateTransferePrestataire", -1 ) ) )
307         {
308             model.put( "messagesServiceFait",
309                     allMessagesServiceFait.get( AppPropertiesService.getPropertyInt( "signalement.idTaskTransferePrestataireNotifMultiContents", -1 ) ) );
310         }
311         else
312         {
313             model.put( "messagesServiceFait", allMessagesServiceFait
314                     .get( AppPropertiesService.getPropertyInt( "signalement.idTaskServiceProgrammePrestataireNotifMultiContents", -1 ) ) );
315         }
316 
317         model.put( _dansmarueUploadHandler.getHandlerName( ), _dansmarueUploadHandler );
318 
319         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_ACTIONS, request.getLocale( ), model );
320 
321         page.setContent( template.getHtml( ) );
322         page.setPathLabel( I18nService.getLocalizedString( I18N_TITLE, request.getLocale( ) ) );
323         page.setTitle( I18nService.getLocalizedString( I18N_TITLE, request.getLocale( ) ) );
324 
325         return page;
326     }
327 
328     /**
329      * Validate the form and return the errors if exists.
330      *
331      * @param request
332      *            the http request
333      * @return the errors or null
334      */
335     private String validateForm( HttpServletRequest request )
336     {
337         String error = null;
338 
339         String action = getAction( request );
340 
341         if ( !StringUtils.isBlank( action ) && ManageSignalementService.ACTION_VALIDER.equals( action ) )
342         {
343             error = I18nService.getLocalizedString( I18N_ERROR_MANDATORY_ACTION, request.getLocale( ) );
344         }
345         else
346             if ( ManageSignalementService.ACTION_REJETER.equals( action ) )
347             {
348                 String [ ] motifsRejetIds = request.getParameterValues( PARAMETER_MOTIF_REJET );
349                 String hasEmailSignaleur = request.getParameter( MARK_HAS_EMAIL_SIGNALEUR );
350                 boolean motifAutreCheckbox = StringUtils.isNotBlank( request.getParameter( PARAMETER_MOTIF_AUTRE_CHECKBOX ) );
351 
352                 boolean emptyMotif = ArrayUtils.isEmpty( motifsRejetIds );
353 
354                 if ( emptyMotif && !motifAutreCheckbox && ( hasEmailSignaleur != null ) )
355                 {
356                     return I18nService.getLocalizedString( I18N_ERROR_MOTIF_REJET, request.getLocale( ) );
357                 }
358 
359                 // Vérification si les motifs sont valides
360                 if ( !emptyMotif )
361                 {
362                     List<ObservationRejet> observationList = _observationRejetService.getAllObservationRejetActif( );
363                     List<ObservationRejet> motifsRejet = new ArrayList<>( );
364                     for ( ObservationRejet observation : observationList )
365                     {
366                         for ( String motifRejetId : motifsRejetIds )
367                         {
368                             Integer motifRejetInt = Integer.parseInt( motifRejetId );
369                             if ( observation.getActif( ) && observation.getId( ).equals( motifRejetInt ) )
370                             {
371                                 motifsRejet.add( observation );
372                             }
373                         }
374                     }
375 
376                     if ( CollectionUtils.isEmpty( motifsRejet ) )
377                     {
378                         return I18nService.getLocalizedString( I18N_ERROR_MOTIF_REJET, request.getLocale( ) );
379                     }
380                 }
381                 String motifAutre = request.getParameter( PARAMETER_MOTIF_AUTRE );
382                 if ( motifAutreCheckbox && StringUtils.isBlank( motifAutre ) )
383                 {
384                     return I18nService.getLocalizedString( I18N_ERROR_MOTIF_REJET, request.getLocale( ) );
385                 }
386 
387             }
388             else
389                 if ( ManageSignalementService.ACTION_PROGRAMMER.equals( action ) && StringUtils.isBlank( request.getParameter( "dateProgrammation" ) ) )
390                 {
391                     error = I18nService.getLocalizedString( I18N_ERROR_PROGRAMMATION_DATE, request.getLocale( ) );
392                 }
393                 else
394                     if ( ManageSignalementService.ACTION_REQUALIFIER.equals( action )
395                             && StringUtils.isBlank( request.getParameter( PARAMETER_ID_TYPE_ANOMALIE ) ) )
396                     {
397 
398                         error = I18nService.getLocalizedString( I18N_ERROR_TYPE_ANOMALIE, request.getLocale( ) );
399                     }
400 
401         return error;
402     }
403 
404     /**
405      * Add motifs to the data model.
406      *
407      * @param model
408      *            the model
409      */
410     private void addMotifs( Map<String, Object> model )
411     {
412         List<ObservationRejet> motifsActifs = _observationRejetService.getAllObservationRejetActif( );
413         model.put( MARK_MOTIFS, motifsActifs );
414     }
415 
416     /**
417      * Add all type Anomalie to the model.
418      *
419      * @param model
420      *            the model
421      * @param signalement
422      *            the report
423      */
424     private void addTypeAnomalie( Map<String, Object> model, Signalement signalement )
425     {
426 
427         // get the type signalement
428         TypeSignalement typeSignalement = _typeSignalementService.getTypeSignalement( signalement.getTypeSignalement( ).getId( ) );
429         model.put( MARK_TYPE, typeSignalement );
430 
431         // get all the type signalement
432         List<TypeSignalement> types = _typeSignalementService.getAllTypeSignalementActif( );
433         ReferenceList listeTypes = _listUtils.toReferenceList( types, "id", "formatTypeSignalement", "", false );
434         model.put( MARK_TYPE_LIST, listeTypes );
435 
436     }
437 
438     /**
439      * Get report if parameters are correct.
440      *
441      * @param request
442      *            the http request
443      * @return the report
444      */
445     private Signalement getSignalement( HttpServletRequest request )
446     {
447         Signalement bean = null;
448         String strIdSignalement = request.getParameter( MARK_ID );
449         String token = request.getParameter( PARAMETER_TOKEN );
450         if ( StringUtils.isNotBlank( strIdSignalement ) && StringUtils.isNumeric( strIdSignalement ) )
451         {
452             Integer id = Integer.valueOf( strIdSignalement );
453             bean = _signalementService.getSignalementWithFullPhoto( id );
454             if ( ( bean != null ) && ( StringUtils.isBlank( token ) || !token.equals( bean.getToken( ) ) ) )
455             {
456                 bean = null;
457                 AppLogService.error( "Cannot get signalement bean with id " + strIdSignalement + " and token " + token );
458             }
459         }
460         return bean;
461     }
462 
463     /**
464      * Get the action asked by user.
465      *
466      * @param request
467      *            the http request
468      * @return the action
469      */
470     private String getAction( HttpServletRequest request )
471     {
472         return request.getParameter( MARK_ACTION );
473     }
474 }