TicketEmailExternalUserTaskComponent.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.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import org.apache.commons.lang.StringUtils;
import fr.paris.lutece.plugins.ticketing.business.ticket.Ticket;
import fr.paris.lutece.plugins.ticketing.business.ticket.TicketHome;
import fr.paris.lutece.plugins.ticketing.web.TicketingConstants;
import fr.paris.lutece.plugins.ticketing.web.util.ModelUtils;
import fr.paris.lutece.plugins.workflow.modules.notifygru.business.TaskNotifyGruConfig;
import fr.paris.lutece.plugins.workflow.modules.notifygru.service.TaskNotifyGruConfigService;
import fr.paris.lutece.plugins.workflow.modules.notifygru.service.provider.IProvider;
import fr.paris.lutece.plugins.workflow.modules.notifygru.service.provider.NotifyGruMarker;
import fr.paris.lutece.plugins.workflow.modules.ticketing.business.email.cc.ITicketEmailExternalUserCcDAO;
import fr.paris.lutece.plugins.workflow.modules.ticketing.business.email.cc.TicketEmailExternalUserCc;
import fr.paris.lutece.plugins.workflow.modules.ticketing.business.email.config.MessageDirectionExternalUser;
import fr.paris.lutece.plugins.workflow.modules.ticketing.business.email.config.TaskTicketEmailExternalUserConfig;
import fr.paris.lutece.plugins.workflow.modules.ticketing.business.email.history.ITicketEmailExternalUserHistoryDAO;
import fr.paris.lutece.plugins.workflow.modules.ticketing.business.email.history.TicketEmailExternalUserHistory;
import fr.paris.lutece.plugins.workflow.modules.ticketing.business.email.message.ITicketEmailExternalUserMessageDAO;
import fr.paris.lutece.plugins.workflow.modules.ticketing.business.email.message.TicketEmailExternalUserMessage;
import fr.paris.lutece.plugins.workflow.modules.ticketing.business.email.provider.TicketEmailExternalUserProviderManager;
import fr.paris.lutece.plugins.workflow.modules.ticketing.business.email.recipient.ITicketEmailExternalUserRecipientDAO;
import fr.paris.lutece.plugins.workflow.modules.ticketing.business.email.recipient.TicketEmailExternalUserRecipient;
import fr.paris.lutece.plugins.workflow.modules.ticketing.business.externaluser.IExternalUserDAO;
import fr.paris.lutece.plugins.workflow.modules.ticketing.service.task.TaskTicketEmailExternalUser;
import fr.paris.lutece.plugins.workflow.modules.ticketing.utils.WorkflowTicketingUtils;
import fr.paris.lutece.plugins.workflowcore.business.config.ITaskConfig;
import fr.paris.lutece.plugins.workflowcore.business.resource.ResourceHistory;
import fr.paris.lutece.plugins.workflowcore.service.action.ActionService;
import fr.paris.lutece.plugins.workflowcore.service.config.ITaskConfigService;
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.plugins.workflowcore.web.task.TaskComponent;
import fr.paris.lutece.portal.business.user.attribute.IAttribute;
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.user.attribute.AttributeService;
import fr.paris.lutece.util.ReferenceList;
import fr.paris.lutece.util.beanvalidation.BeanValidationUtil;
import fr.paris.lutece.util.html.HtmlTemplate;
/**
* Class for the TicketEmailExternalUser task
*/
/**
* @author a120274
*
*/
public class TicketEmailExternalUserTaskComponent extends TaskComponent
{
// TEMPLATES
private static final String TEMPLATE_TASK_TICKET_CONFIG = "admin/plugins/workflow/modules/ticketing/external_user/task_ticket_email_external_user_config.html";
private static final String TEMPLATE_TASK_TICKET_FORM = "admin/plugins/workflow/modules/ticketing/external_user/task_ticket_email_external_user_form.html";
private static final String TEMPLATE_TASK_TICKET_INFORMATION = "admin/plugins/workflow/modules/ticketing/external_user/task_ticket_email_external_user_informations.html";
// Marks
private static final String MARK_CONFIG = "config";
private static final String MARK_CONFIG_FOLLOW_ACTION_ID = "following_action_id";
private static final String MARK_TICKETING_MESSAGE = "external_user_message";
private static final String MARK_TICKETING_EMAIL_INFO_CC = "email_infos_cc";
private static final String MARK_TICKETING_LIST_EMAIL_INFOS = "list_email_infos";
private static final String MARK_MESSAGE_DIRECTIONS_LIST = "message_directions_list";
private static final String MARK_MESSAGE_DIRECTION = "message_direction";
private static final String MARK_CONFIG_CONTACT_ATTRIBUTE = "contact_attribute_id";
private static final String MARK_CONFIG_DEFAULT_SUBJECT = "default_subject";
private static final String MARK_CONFIG_LABEL_ATTRIBUTE = "label_contact_attribute";
private static final String MARK_TICKET_COMMENT = "ticket_comment";
// Parameters config
private static final String PARAMETER_MESSAGE_DIRECTION = "message_direction";
private static final String PARAMETER_FOLLOW_ACTION_ID = "following_action_id";
private static final String PARAMETER_CONTACT_ATTRIBUTE = "contact_attribute_id";
private static final String PARAMETER_DEFAULT_SUBJECT = "default_subject";
// Error message
public static final String MESSAGE_EMPTY_EMAIL = "module.workflow.ticketing.task_ticket_email_external_user.error.email.empty";
public static final String MESSAGE_INVALID_EMAIL_OR_NOT_AUTHORIZED = "module.workflow.ticketing.task_ticket_email_external_user.error.email.invalid.not_authorized";
public static final String MESSAGE_INVALID_EMAIL = "module.workflow.ticketing.task_ticket_email_external_user.error.email.invalid";
private static final String MESSAGE_ALREADY_ANSWER = "module.workflow.ticketing.externalUserResponse.message.already_answer";
private static final String MESSAGE_EMPTY_FIELD = "module.workflow.ticketing.task_ticket_email_external_user.error.field.empty";
// Constant
private static final String DISPLAY_SEMICOLON = " ; ";
private static final AttributeService _attributeService = AttributeService.getInstance( );
@Inject
@Named( TaskTicketEmailExternalUser.BEAN_TICKET_CONFIG_SERVICE )
private ITaskConfigService _taskTicketConfigService;
@Inject
@Named( ITicketEmailExternalUserHistoryDAO.BEAN_SERVICE )
private ITicketEmailExternalUserHistoryDAO _ticketEmailExternalUserHistoryDAO;
@Inject
@Named( ITicketEmailExternalUserRecipientDAO.BEAN_SERVICE )
private ITicketEmailExternalUserRecipientDAO _ticketEmailExternalUserRecipientDAO;
@Inject
@Named( ITicketEmailExternalUserCcDAO.BEAN_SERVICE )
private ITicketEmailExternalUserCcDAO _ticketEmailExternalUserCcDAO;
@Inject
@Named( ITicketEmailExternalUserMessageDAO.BEAN_SERVICE )
private ITicketEmailExternalUserMessageDAO _ticketEmailExternalUserMessageDAO;
@Inject
@Named( ActionService.BEAN_SERVICE )
private ActionService _actionService;
@Inject
@Named( IExternalUserDAO.BEAN_SERVICE )
private IExternalUserDAO _ExternalUserDAO;
@Inject
@Named( TaskService.BEAN_SERVICE )
private ITaskService _taskService;
@Inject
@Named( TaskNotifyGruConfigService.BEAN_SERVICE )
private ITaskConfigService _taskNotifyGruConfigService;
@Inject
@Named( "workflow-ticketing.externaluser.provider-manager" )
private TicketEmailExternalUserProviderManager _ticketEmailExternalUserProviderManager;
/**
* {@inheritDoc}
*/
@Override
public String getDisplayTaskInformation( int nIdHistory, HttpServletRequest request, Locale locale, ITask task )
{
TicketEmailExternalUserHistory emailExternalUserHistory = _ticketEmailExternalUserHistoryDAO.loadByIdHistory( nIdHistory );
TicketEmailExternalUserMessage mailExternalUserMessage = _ticketEmailExternalUserMessageDAO
.loadByIdMessageExternalUser( emailExternalUserHistory.getIdMessageExternalUser( ) );
TaskTicketEmailExternalUserConfig config = getTaskConfigService( ).findByPrimaryKey( task.getId( ) );
Map<String, Object> model = new HashMap<>( );
String messageQuestion = mailExternalUserMessage != null ? mailExternalUserMessage.getMessageQuestion( ) : "";
if ( ( config != null ) && ( config.getMessageDirectionExternalUser( ) == MessageDirectionExternalUser.AGENT_TO_EXTERNAL_USER ) )
{
model.put( MARK_TICKETING_MESSAGE, TicketingConstants.MESSAGE_MARK + messageQuestion );
List<TicketEmailExternalUserRecipient> listRecipientEmailExternalUser = _ticketEmailExternalUserRecipientDAO.loadByIdHistory( nIdHistory,
task.getId( ) );
List<TicketEmailExternalUserCc> listCcEmailExternalUser = _ticketEmailExternalUserCcDAO.loadByIdHistory( nIdHistory, task.getId( ) );
StringBuilder sbInfosCc = new StringBuilder( );
for ( TicketEmailExternalUserCc emailExternalUserCc : listCcEmailExternalUser )
{
sbInfosCc.append( emailExternalUserCc.getEmail( ) ).append( DISPLAY_SEMICOLON );
}
if ( sbInfosCc.length( ) > 0 )
{
sbInfosCc.setLength( sbInfosCc.length( ) - 3 );
}
model.put( MARK_TICKETING_LIST_EMAIL_INFOS, listRecipientEmailExternalUser );
model.put( MARK_TICKETING_EMAIL_INFO_CC, sbInfosCc.toString( ) );
}
else
if ( ( config != null ) && ( config.getMessageDirectionExternalUser( ) == MessageDirectionExternalUser.RE_AGENT_TO_EXTERNAL_USER ) )
{
model.put( MARK_TICKETING_MESSAGE, TicketingConstants.MESSAGE_MARK + messageQuestion );
}
else
{
String messageResponse = mailExternalUserMessage != null ? mailExternalUserMessage.getMessageResponse( ) : "";
model.put( MARK_TICKETING_MESSAGE, TicketingConstants.MESSAGE_MARK + messageResponse );
}
HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_TASK_TICKET_INFORMATION, locale, model );
return template.getHtml( );
}
/**
* {@inheritDoc}
*/
@Override
public String getDisplayTaskForm( int nIdResource, String strResourceType, HttpServletRequest request, Locale locale, ITask task )
{
TaskTicketEmailExternalUserConfig config = getTaskConfigService( ).findByPrimaryKey( task.getId( ) );
if ( config != null )
{
List<ITask> taskList = _taskService.getListTaskByIdAction( task.getAction( ).getId( ), locale );
for ( ITask taskItem : taskList )
{
String key = taskItem.getTaskType( ).getKey( );
if ( "taskNotifyGru".equals( key ) )
{
TaskNotifyGruConfig configNotify = _taskNotifyGruConfigService.findByPrimaryKey( taskItem.getId( ) );
if ( configNotify != null )
{
String strProviderId = "ticketEmailExternalUserProviderManager";
ResourceHistory resourceHistory = new ResourceHistory( );
resourceHistory.setIdResource( nIdResource );
IProvider provider = _ticketEmailExternalUserProviderManager.createProvider( strProviderId, resourceHistory, request );
Collection<NotifyGruMarker> markerValues = provider.provideMarkerValues( );
String subject = config.getDefaultSubject( );
if ( StringUtils.isBlank( subject ) )
{
subject = configNotify.getSubjectBroadcast( );
}
for ( NotifyGruMarker marker : markerValues )
{
String markerKey = marker.getMarker( );
if ( markerKey != null )
{
String markerValue = marker.getValue( );
String value = markerValue != null ? markerValue : "";
subject = subject.replace( "${" + markerKey + "}", value );
subject = subject.replace( "${" + markerKey + "!}", ( value != null ) && !"".equals( value ) ? value : "" );
}
}
subject = subject.replaceAll( "\\$\\{.*\\}", "" );
config.setDefaultSubject( subject );
}
}
}
}
Map<String, Object> model = new HashMap<>( );
model.put( MARK_CONFIG, config );
String strLabelContactAttribute = StringUtils.EMPTY;
if ( ( config != null ) && ( config.getIdContactAttribute( ) != null ) )
{
IAttribute attribute = _attributeService.getAttributeWithFields( config.getIdContactAttribute( ), locale );
if ( attribute != null )
{
strLabelContactAttribute = attribute.getTitle( );
}
}
model.put( MARK_CONFIG_LABEL_ATTRIBUTE, strLabelContactAttribute );
ModelUtils.storeRichText( request, model );
ModelUtils.storeUserSignature( request, model );
Ticket ticket = TicketHome.findByPrimaryKey( nIdResource );
model.put( MARK_TICKET_COMMENT, ticket != null ? ticket.getTicketComment( ).replace( "\r\n", "<br>" ) : "" );
HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_TASK_TICKET_FORM, locale, model );
return template.getHtml( );
}
/**
* {@inheritDoc}
*/
public String getTaskInformationXml( int nIdHistory, HttpServletRequest request, Locale locale, ITask task )
{
return null;
}
/**
* {@inheritDoc}
*/
@Override
public String validateConfig( ITaskConfig config, HttpServletRequest request )
{
Set<ConstraintViolation<ITaskConfig>> setConstraintErrors = BeanValidationUtil.validate( config );
if ( !setConstraintErrors.isEmpty( ) )
{
return AdminMessageService.getMessageUrl( request, MESSAGE_EMPTY_FIELD, AdminMessage.TYPE_ERROR );
}
return null;
}
/**
* {@inheritDoc}
*/
@Override
public String doValidateTask( int nIdResource, String strResourceType, HttpServletRequest request, Locale locale, ITask task )
{
TaskTicketEmailExternalUserConfig config = getTaskConfigService( ).findByPrimaryKey( task.getId( ) );
String strNextActionId = String.valueOf( config.getIdFollowingAction( ) );
String strEmailRecipients = request
.getParameter( TaskTicketEmailExternalUser.PARAMETER_EMAIL_RECIPIENTS + TaskTicketEmailExternalUser.UNDERSCORE + task.getId( ) );
String strEmailRecipientsCc = request
.getParameter( TaskTicketEmailExternalUser.PARAMETER_EMAIL_RECIPIENTS_CC + TaskTicketEmailExternalUser.UNDERSCORE + task.getId( ) );
String strEmailSubject = request
.getParameter( TaskTicketEmailExternalUser.PARAMETER_EMAIL_SUBJECT + TaskTicketEmailExternalUser.UNDERSCORE + task.getId( ) );
String strError = null;
int nLevelError = -1;
Object [ ] errorParams = new Object [ 1];
// TODO SI PAS D'OBJET, ERREUR !
if ( config.getMessageDirectionExternalUser( ) == MessageDirectionExternalUser.AGENT_TO_EXTERNAL_USER )
{
if ( StringUtils.isEmpty( strEmailRecipients ) )
{
strError = MESSAGE_EMPTY_EMAIL;
nLevelError = AdminMessage.TYPE_STOP;
}
else
{
List<String> listErrorRecipients = WorkflowTicketingUtils.validEmailList( strEmailRecipients, _ExternalUserDAO, strNextActionId );
if ( !listErrorRecipients.isEmpty( ) )
{
strError = listErrorRecipients.get( 0 );
nLevelError = AdminMessage.TYPE_STOP;
if ( listErrorRecipients.size( ) > 1 )
{
errorParams = listErrorRecipients.subList( 1, listErrorRecipients.size( ) ).toArray( );
}
}
}
if ( ( strError == null ) && StringUtils.isNotEmpty( strEmailRecipientsCc ) )
{
List<String> listErrorRecipientsCc = WorkflowTicketingUtils.validEmailList( strEmailRecipientsCc, null, null );
if ( !listErrorRecipientsCc.isEmpty( ) )
{
strError = listErrorRecipientsCc.get( 0 );
nLevelError = AdminMessage.TYPE_STOP;
if ( listErrorRecipientsCc.size( ) > 1 )
{
errorParams = listErrorRecipientsCc.subList( 1, listErrorRecipientsCc.size( ) ).toArray( );
}
}
}
}
if ( ( config.getMessageDirectionExternalUser( ) == MessageDirectionExternalUser.EXTERNAL_USER_TO_AGENT ) )
{
TicketEmailExternalUserMessage lastExternalUserMessage = _ticketEmailExternalUserMessageDAO.loadLastByIdTicket( nIdResource );
if ( ( lastExternalUserMessage == null ) || ( lastExternalUserMessage.getIsAnswered( ) )
|| ( !_ticketEmailExternalUserMessageDAO.isLastQuestion( nIdResource, lastExternalUserMessage.getIdMessageExternalUser( ) ) ) )
{
strError = MESSAGE_ALREADY_ANSWER;
nLevelError = AdminMessage.TYPE_WARNING;
}
}
if ( ( strError != null ) && ( nLevelError >= 0 ) )
{
return AdminMessageService.getMessageUrl( request, strError, errorParams, nLevelError );
}
return StringUtils.EMPTY;
}
/**
* {@inheritDoc}
*/
@Override
public String getDisplayConfigForm( HttpServletRequest request, Locale locale, ITask task )
{
Map<String, Object> model = new HashMap<>( );
TaskTicketEmailExternalUserConfig config = getTaskConfigService( ).findByPrimaryKey( task.getId( ) );
ReferenceList listMessageDirections = MessageDirectionExternalUser.getReferenceList( locale );
model.put( MARK_MESSAGE_DIRECTIONS_LIST, listMessageDirections );
model.put( MARK_CONFIG_FOLLOW_ACTION_ID, StringUtils.EMPTY );
model.put( MARK_CONFIG_CONTACT_ATTRIBUTE, StringUtils.EMPTY );
model.put( MARK_CONFIG_DEFAULT_SUBJECT, StringUtils.EMPTY );
if ( config != null )
{
model.put( MARK_MESSAGE_DIRECTION, config.getMessageDirectionExternalUser( ).ordinal( ) );
if ( config.getIdFollowingAction( ) != null )
{
model.put( MARK_CONFIG_FOLLOW_ACTION_ID, config.getIdFollowingAction( ) );
}
if ( config.getIdContactAttribute( ) != null )
{
model.put( MARK_CONFIG_CONTACT_ATTRIBUTE, config.getIdContactAttribute( ) );
}
if ( config.getDefaultSubject( ) != null )
{
model.put( MARK_CONFIG_DEFAULT_SUBJECT, config.getDefaultSubject( ) );
}
}
else
{
model.put( MARK_MESSAGE_DIRECTION, MessageDirectionExternalUser.AGENT_TO_EXTERNAL_USER );
}
model.put( MARK_CONFIG, config );
HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_TASK_TICKET_CONFIG, locale, model );
return template.getHtml( );
}
/**
* {@inheritDoc}
*/
@Override
public String doSaveConfig( HttpServletRequest request, Locale locale, ITask task )
{
Integer nMessageDirectionId = getParameterAsInteger( request.getParameter( PARAMETER_MESSAGE_DIRECTION ) );
Integer nIdFollowingAction = getParameterAsInteger( request.getParameter( PARAMETER_FOLLOW_ACTION_ID ) );
Integer nIdContactAttribute = getParameterAsInteger( request.getParameter( PARAMETER_CONTACT_ATTRIBUTE ) );
String strDefaultSubject = request.getParameter( PARAMETER_DEFAULT_SUBJECT );
TaskTicketEmailExternalUserConfig config = getTaskConfigService( ).findByPrimaryKey( task.getId( ) );
boolean bConfigToCreate = false;
if ( config == null )
{
config = new TaskTicketEmailExternalUserConfig( );
config.setIdTask( task.getId( ) );
bConfigToCreate = true;
}
config.setMessageDirectionExternalUser( MessageDirectionExternalUser.valueOf( nMessageDirectionId ) );
config.setIdFollowingAction( nIdFollowingAction );
config.setIdContactAttribute( nIdContactAttribute );
config.setDefaultSubject( strDefaultSubject );
String strJspError = validateConfig( config, request );
if ( StringUtils.isNotBlank( strJspError ) )
{
return strJspError;
}
if ( bConfigToCreate )
{
getTaskConfigService( ).create( config );
}
else
{
getTaskConfigService( ).update( config );
}
return null;
}
/**
*
* @param strParameter
* @return the parameter value parsed as Integer
*/
private Integer getParameterAsInteger( String strParameter )
{
if ( StringUtils.isNotBlank( strParameter ) && StringUtils.isNumeric( strParameter ) )
{
return Integer.parseInt( strParameter );
}
return null;
}
}