ModifyTicketCategoryTaskComponent.java
/*
* Copyright (c) 2002-2024, 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.workflow.modules.ticketing.web.task;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
import fr.paris.lutece.plugins.genericattributes.business.Entry;
import fr.paris.lutece.plugins.genericattributes.business.EntryFilter;
import fr.paris.lutece.plugins.genericattributes.business.EntryHome;
import fr.paris.lutece.plugins.genericattributes.business.GenericAttributeError;
import fr.paris.lutece.plugins.ticketing.business.category.TicketCategory;
import fr.paris.lutece.plugins.ticketing.business.ticket.Ticket;
import fr.paris.lutece.plugins.ticketing.service.TicketFormService;
import fr.paris.lutece.plugins.ticketing.service.category.TicketCategoryService;
import fr.paris.lutece.plugins.ticketing.web.TicketingConstants;
import fr.paris.lutece.plugins.ticketing.web.util.TicketCategoryValidator;
import fr.paris.lutece.plugins.ticketing.web.util.TicketCategoryValidatorResult;
import fr.paris.lutece.plugins.workflow.modules.ticketing.business.config.TaskModifyTicketCategoryConfig;
import fr.paris.lutece.plugins.workflow.modules.ticketing.utils.UtilConstants;
import fr.paris.lutece.plugins.workflowcore.service.task.ITask;
import fr.paris.lutece.portal.service.i18n.I18nService;
import fr.paris.lutece.portal.service.message.AdminMessage;
import fr.paris.lutece.portal.service.message.AdminMessageService;
import fr.paris.lutece.portal.service.template.AppTemplateService;
import fr.paris.lutece.portal.service.util.AppPropertiesService;
import fr.paris.lutece.util.ReferenceItem;
import fr.paris.lutece.util.ReferenceList;
import fr.paris.lutece.util.html.HtmlTemplate;
/**
* This class is a component for the task {@link fr.paris.lutece.plugins.workflow.modules.ticketing.service.task.TaskModifyTicketCategory}
*
*/
public class ModifyTicketCategoryTaskComponent extends TicketingTaskComponent
{
// TEMPLATES
private static final String TEMPLATE_TASK_MODIFY_TICKET_CATEGORY_FORM = "admin/plugins/workflow/modules/ticketing/task_modify_ticket_category_form.html";
private static final String TEMPLATE_TASK_MODIFY_TICKET_CATEGORY_CONFIG = "admin/plugins/workflow/modules/ticketing/task_modify_ticket_category_config.html";
// MARKS
private static final String MARK_CONFIG = "config";
private static final String MARK_CONFIG_ALL_ENTRY = "form_entries";
private static final String MARK_CONFIG_SELECTED_ENTRY = "selected_form_entry";
private static final String MARK_ID_TASK = "id_task";
// Message reply
private static final String MESSAGE_MODIFY_TICKET_ATTRIBUTE_ERROR = "module.workflow.ticketing.task_modify_ticket_attribute.error";
@Inject
private TicketFormService _ticketFormService;
private static final String PROPERTY_ACCOUNT_NUMBER_REGEXP = "module.workflow.ticketingfacilfamilles.workflow.automatic_assignment.accountNumberRegexp";
private static final String PROPERTY_FF_CODE = "module.workflow.ticketingfacilfamilles.workflow.automatic_assignment.accountNumberFieldCode";
private static final String MESSAGE_ERROR_FACIL_EMPTY_VALIDATION = "ticketing.validation.ticket.TicketFacilNumber.size";
private static final String MESSAGE_ERROR_FACIL_REGEX_VALIDATION = "ticketing.validation.ticket.TicketFacilNumber.regex";
/**
* {@inheritDoc}
*/
@Override
public String getDisplayConfigForm( HttpServletRequest request, Locale locale, ITask task )
{
TaskModifyTicketCategoryConfig config = getTaskConfigService( ).findByPrimaryKey( task.getId( ) );
EntryFilter entryFilter = new EntryFilter( );
entryFilter.setResourceType( TicketingConstants.RESOURCE_TYPE_INPUT );
entryFilter.setEntryParentNull( EntryFilter.FILTER_TRUE );
entryFilter.setFieldDependNull( EntryFilter.FILTER_TRUE );
entryFilter.setIdIsComment( EntryFilter.FILTER_FALSE );
List<Entry> lReferenceEntry = EntryHome.getEntryList( entryFilter );
Map<String, Object> model = new HashMap<>( );
model.put( MARK_CONFIG, config );
model.put( MARK_CONFIG_ALL_ENTRY, mergeConfigAndReference( config, lReferenceEntry ) );
HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_TASK_MODIFY_TICKET_CATEGORY_CONFIG, locale, model );
return template.getHtml( );
}
private ReferenceList mergeConfigAndReference( TaskModifyTicketCategoryConfig config, List<Entry> lReferenceEntry )
{
ReferenceList refList = new ReferenceList( );
for ( Entry refEntry : lReferenceEntry )
{
ReferenceItem refItem = new ReferenceItem( );
refItem.setCode( Integer.toString( refEntry.getIdEntry( ) ) );
refItem.setName( refEntry.getTitle( ) + " (" + refEntry.getEntryType( ).getTitle( ) + ")" );
refItem.setChecked( config.getSelectedEntries( ).contains( refEntry.getIdEntry( ) ) );
refList.add( refItem );
}
return refList;
}
/**
* {@inheritDoc}
*/
@Override
public String doSaveConfig( HttpServletRequest request, Locale locale, ITask task )
{
TaskModifyTicketCategoryConfig config = getTaskConfigService( ).findByPrimaryKey( task.getId( ) );
String [ ] tSelectedEntries = new String [ ] { };
config.clearSelectedEntries( );
if ( request.getParameterValues( MARK_CONFIG_SELECTED_ENTRY ) != null )
{
tSelectedEntries = request.getParameterValues( MARK_CONFIG_SELECTED_ENTRY );
}
for ( String strSelectedEntry : tSelectedEntries )
{
config.addSelectedEntry( Integer.parseInt( strSelectedEntry ) );
}
getTaskConfigService( ).update( config );
return null;
}
/**
* {@inheritDoc}
*/
@Override
public String getDisplayTaskForm( int nIdResource, String strResourceType, HttpServletRequest request, Locale locale, ITask task )
{
Ticket ticket = getTicket( nIdResource, strResourceType );
_ticketFormService.saveTicketInSession( request.getSession( ), ticket );
Map<String, Object> model = getModel( ticket );
model.put( TicketingConstants.MARK_TICKET_CATEGORIES_TREE, TicketCategoryService.getInstance( true ).getCategoriesTree( ).getTreeJSONObject( ) );
model.put( TicketingConstants.MARK_TICKET_CATEGORIES_DEPTHS, TicketCategoryService.getInstance( true ).getCategoriesTree( ).getDepths( ) );
model.put( MARK_ID_TASK, task.getId( ) );
HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_TASK_MODIFY_TICKET_CATEGORY_FORM, locale, model );
return template.getHtml( );
}
/**
* {@inheritDoc}
*/
@Override
public String doValidateTask( int nIdResource, String strResourceType, HttpServletRequest request, Locale locale, ITask task )
{
Ticket ticket = getTicket( nIdResource, strResourceType );
StringBuilder strError = new StringBuilder( StringUtils.EMPTY );
List<String> listErrors = new ArrayList<>( );
TicketCategoryValidatorResult categoryValidatorResult = new TicketCategoryValidator( request, locale ).validateTicketCategory( );
// Check if a category have been selected
if ( !categoryValidatorResult.isTicketCategoryValid( ) )
{
categoryValidatorResult.getListValidationErrors( ).stream( ).forEach( listErrors::add );
}
// Validate the selection of items
if ( categoryValidatorResult.isTicketCategoryValid( ) )
{
List<GenericAttributeError> listFormErrors = new ArrayList<>( );
TaskModifyTicketCategoryConfig config = getTaskConfigService( ).findByPrimaryKey( task.getId( ) );
List<Entry> listEntry = TicketFormService.getFilterInputs( ticket.getTicketCategory( ).getId( ), config.getSelectedEntries( ) );
boolean hasFFError = false;
for ( Entry entry : listEntry )
{
listFormErrors.addAll( _ticketFormService.getResponseEntry( request, entry.getIdEntry( ), request.getLocale( ), ticket ) );
// O2T 79251: contrôle facil'famille
if ( !hasFFError && isDomainFacilFamille( categoryValidatorResult.getTicketCategory( ) ) )
{
for ( GenericAttributeError error : listFormErrors )
{
if ( error.getErrorMessage( ).contains( "Facil'Famille" ) || error.getErrorMessage( ).contains( UtilConstants.CATEGORY_LABEL_PARIS_FAMILLE ) )
{
hasFFError = true;
break;
}
}
if ( !hasFFError && entry.getCode( ).equals( AppPropertiesService.getProperty( PROPERTY_FF_CODE ) ) )
{
String strFacilFamilleNumber = request.getParameter( "attribute" + entry.getIdEntry( ) );
if ( strFacilFamilleNumber != null )
{
if ( strFacilFamilleNumber.trim( ).isEmpty( ) )
{
GenericAttributeError formError = new GenericAttributeError( );
formError.setErrorMessage( I18nService.getLocalizedString( MESSAGE_ERROR_FACIL_EMPTY_VALIDATION, request.getLocale( ) ) );
listFormErrors.add( formError );
hasFFError = true;
}
else
if ( !strFacilFamilleNumber.matches( AppPropertiesService.getProperty( PROPERTY_ACCOUNT_NUMBER_REGEXP ) ) )
{
GenericAttributeError formError = new GenericAttributeError( );
formError.setErrorMessage( I18nService.getLocalizedString( MESSAGE_ERROR_FACIL_REGEX_VALIDATION, request.getLocale( ) ) );
listFormErrors.add( formError );
hasFFError = true;
}
}
}
}
}
// O2T 79251: contrôle facil'famille
if ( listEntry.isEmpty( ) && isDomainFacilFamille( categoryValidatorResult.getTicketCategory( ) ) )
{
GenericAttributeError facilFamilleError = getFacilFamilleError( request );
if ( facilFamilleError != null )
{
listFormErrors.add( facilFamilleError );
}
}
if ( !listFormErrors.isEmpty( ) )
{
for ( GenericAttributeError formError : listFormErrors )
{
strError.append( formError.getErrorMessage( ) ).append( "<br/>" );
}
listErrors.add( strError.toString( ) );
}
}
if ( !listErrors.isEmpty( ) )
{
return AdminMessageService.getMessageUrl( request, MESSAGE_MODIFY_TICKET_ATTRIBUTE_ERROR, listErrors.toArray( ), AdminMessage.TYPE_STOP );
}
return null;
}
private GenericAttributeError getFacilFamilleError( HttpServletRequest request )
{
String strFacilFamilleNumber = request.getParameter( "attribute202" );
if ( strFacilFamilleNumber != null )
{
if ( strFacilFamilleNumber.trim( ).isEmpty( ) )
{
GenericAttributeError formError = new GenericAttributeError( );
formError.setErrorMessage( I18nService.getLocalizedString( MESSAGE_ERROR_FACIL_EMPTY_VALIDATION, request.getLocale( ) ) );
return formError;
}
else
if ( !strFacilFamilleNumber.matches( AppPropertiesService.getProperty( PROPERTY_ACCOUNT_NUMBER_REGEXP ) ) )
{
GenericAttributeError formError = new GenericAttributeError( );
formError.setErrorMessage( I18nService.getLocalizedString( MESSAGE_ERROR_FACIL_REGEX_VALIDATION, request.getLocale( ) ) );
return formError;
}
}
return null;
}
private boolean isDomainFacilFamille( TicketCategory category )
{
if ( category != null )
{
if ( category.getDepth( ).getDepthNumber( ) > 1 )
{
return isDomainFacilFamille( category.getParent( ) );
}
else
if ( category.getDepth( ).getDepthNumber( ) == 1 )
{
return category.getLabel( ).equals( UtilConstants.CATEGORY_LABEL_PARIS_FAMILLE );
}
else
{
// ne devrait pas se produire (0 ou négatif)
return false;
}
}
return false;
}
}