NotificationJspBean.java
/*
* Copyright (c) 2002-2018, Mairie de 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.stock.modules.billetterie.web;
import fr.paris.lutece.plugins.stock.business.attribute.AbstractAttributeNum;
import fr.paris.lutece.plugins.stock.business.attribute.product.ProductAttributeNum;
import fr.paris.lutece.plugins.stock.business.attribute.purchase.PurchaseAttribute;
import fr.paris.lutece.plugins.stock.business.offer.Offer;
import fr.paris.lutece.plugins.stock.business.product.Product;
import fr.paris.lutece.plugins.stock.business.product.ProductFilter;
import fr.paris.lutece.plugins.stock.business.provider.Provider;
import fr.paris.lutece.plugins.stock.business.provider.ProviderFilter;
import fr.paris.lutece.plugins.stock.business.purchase.Purchase;
import fr.paris.lutece.plugins.stock.business.purchase.PurchaseFilter;
import fr.paris.lutece.plugins.stock.commons.ResultList;
import fr.paris.lutece.plugins.stock.commons.exception.FunctionnalException;
import fr.paris.lutece.plugins.stock.modules.billetterie.utils.constants.BilletterieConstants;
import fr.paris.lutece.plugins.stock.modules.tickets.business.*;
import fr.paris.lutece.plugins.stock.modules.tickets.service.*;
import fr.paris.lutece.plugins.stock.modules.tickets.utils.constants.TicketsConstants;
import fr.paris.lutece.plugins.stock.service.IProductService;
import fr.paris.lutece.plugins.stock.utils.constants.StockConstants;
import fr.paris.lutece.portal.service.i18n.I18nService;
import fr.paris.lutece.portal.service.spring.SpringContextService;
import fr.paris.lutece.portal.service.template.AppTemplateService;
import fr.paris.lutece.portal.service.util.AppPathService;
import fr.paris.lutece.portal.service.util.AppPropertiesService;
import fr.paris.lutece.util.html.HtmlTemplate;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import java.util.*;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;
import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.mapping;
/**
* This class provides the user interface to manage notifications
*/
public class NotificationJspBean extends AbstractJspBean
{
public static final Logger LOGGER = Logger.getLogger( NotificationJspBean.class );
public static final String RESOURCE_TYPE = "STOCK";
public static final String RIGHT_MANAGE_NOTIFICATIONS = "OFFERS_MANAGEMENT";
// MARKS
public static final String MARK_NOTIFICATION = "notification";
public static final String MARK_TITLE = "title";
public static final String MARK_OFFER_ID = "offer_id";
public static final String MARK_CANCEL = "cancel";
public static final String MARK_NOTIFY = "notify";
public static final String MARK_LOCK = "lock";
public static final String MARK_NOTIFICATION_ACTION = "notificationAction";
public static final String MARK_AVERTISSEMENT = "avertissement";
public static final String MARK_SEANCE = "seance";
public static final String MARK_LIST_RESERVATION = "liste_reservations";
public static final String MARK_TARIF_REDUIT_ID = "idTarifReduit";
public static final String MARK_BASE_URL = "base_url";
public static final String MARK_PARTNER_CONTACT_MAIL = "partner_contact_mail";
// BEAN
private static final String BEAN_STOCK_TICKETS_SEANCE_SERVICE = "stock-tickets.seanceService";
private static final String BEAN_STOCK_TICKETS_RESERVATION_DAO = "stock-tickets.reservationDAO";
// JSP
private static final String JSP_MANAGE_OFFERS = "jsp/admin/plugins/stock/modules/billetterie/ManageOffers.jsp";
private static final String JSP_SEND_NOTIFICATION = "SendNotification.jsp";
// TEMPLATES
private static final String TEMPLATE_SEND_NOTIFICATION = "admin/plugins/stock/modules/billetterie/send_notification.html";
private static final String TEMPLATE_MAIL_LOCK = "admin/plugins/stock/modules/billetterie/mail_lock.html";
private static final String TEMPLATE_MAIL_CANCEL = "admin/plugins/stock/modules/billetterie/mail_cancel.html";
// PAGE TITLES
private static final String PROPERTY_PAGE_TITLE_SEND_NOTIFICATION = "module.stock.billetterie.send_notification.title";
private static final String PROPERTY_MAIL_SEPARATOR = "mail.list.separator";
// MESSAGES
private static final String MESSAGE_AVERTISSEMENT_CANCEL_OFFER = "module.stock.billetterie.message.cancelOffer.avertissement";
private static final String MESSAGE_AVERTISSEMENT_SEND_OFFER = "module.stock.billetterie.message.sendOffer.avertissement";
private static final String MESSAGE_NOTIFICATION_CANCEL_SUBJECT = "module.stock.billetterie.notification.cancel.subject";
private static final String MESSAGE_NOTIFICATION_BOOKING_LIST_SUBJECT = "module.stock.billetterie.notification.bookingList.subject";
// ORDER FILTER
private static final String ORDER_FILTER_USER_NAME = "userName";
private ISeanceService _serviceOffer;
private IPurchaseService _servicePurchase;
private INotificationService _serviceNotification;
private IProviderService _serviceProvider;
private IShowService _serviceShow;
/** The _dao purchase. */
private IReservationDAO _daoPurchase;
/**
* Instantiates a new notification jsp bean.
*/
public NotificationJspBean( )
{
super( );
_serviceOffer = (ISeanceService) SpringContextService.getBean( BEAN_STOCK_TICKETS_SEANCE_SERVICE );
_servicePurchase = SpringContextService.getContext( ).getBean( IPurchaseService.class );
_serviceNotification = SpringContextService.getContext( ).getBean( INotificationService.class );
_serviceProvider = SpringContextService.getContext( ).getBean( IProviderService.class );
_serviceShow = SpringContextService.getContext( ).getBean( IShowService.class );
_daoPurchase = (IReservationDAO) SpringContextService.getContext( ).getBean( BEAN_STOCK_TICKETS_RESERVATION_DAO );
}
/**
* Returns the form for notification creation
*
* @param request
* The HTTP request
* @return HTML Form
*/
public String getSendNotification( HttpServletRequest request )
{
NotificationDTO notification;
Map<String, Object> model = new HashMap<String, Object>( );
// Manage validation errors
FunctionnalException ve = getErrorOnce( request );
if ( ve != null )
{
notification = (NotificationDTO) ve.getBean( );
model.put( BilletterieConstants.ERROR, getHtmlError( ve ) );
}
else
{
setPageTitleProperty( PROPERTY_PAGE_TITLE_SEND_NOTIFICATION );
// Create new notification
notification = new NotificationDTO( );
}
String strIdOffer = request.getParameter( MARK_OFFER_ID );
String strCancel = request.getParameter( MARK_CANCEL );
String strNotify = request.getParameter( MARK_NOTIFY );
String strLock = request.getParameter( MARK_LOCK );
Integer idOffer = Integer.parseInt( strIdOffer );
SeanceDTO seanceDto = new SeanceDTO( );
seanceDto = ofNullable( idOffer ).map( e -> _serviceOffer.findSeanceById( e ) ).orElse( null );
ShowDTO showDto = ofNullable( seanceDto ).map( e -> e.getProduct( ) ).orElse( null );
Product productById = ofNullable(showDto).map( e ->_serviceShow.getProductById(e.getId()) ).orElse(null);
PurchaseFilter filter = new PurchaseFilter( );
List<ReservationDTO> listReservations = new ArrayList<>( );
Set<ReservationDTO> listReservationsPurchaseByUsername = new HashSet<>();
Set<ReservationDTO> listReservationsPurchase = new HashSet<>();
List<String> listContact = new ArrayList<>( );
// If the notification is about an offer
if ( StringUtils.isNotEmpty( strIdOffer ) )
{
SeanceDTO seance = this._serviceOffer.findSeanceById( idOffer );
notification.setIdOffer( idOffer );
List<String> orderList = new ArrayList<String>( );
orderList.add( ORDER_FILTER_USER_NAME );
filter.setOrders( orderList );
filter.setOrderAsc( true );
filter.setIdOffer( idOffer );
listReservations = this._servicePurchase.findByFilter( filter, null );
Map<String, Integer> reservationDtoByUsername = listReservations.stream()
.collect(groupingBy(ReservationDTO::getUserName, Collectors.summingInt(ReservationDTO::getQuantity)
));
listReservationsPurchaseByUsername = listReservations.stream()
.collect(Collectors.toCollection(() ->
new TreeSet<>(Comparator.comparing(ReservationDTO::getUserName))));
if (reservationDtoByUsername != null) {
for (ReservationDTO reservationDTO:listReservationsPurchaseByUsername) {
reservationDTO.setQuantity(reservationDtoByUsername.get(reservationDTO.getUserName()));
listReservationsPurchase.add(reservationDTO);
}
}
// If the action is to cancel the offer
if ( StringUtils.isNotEmpty( strCancel )
|| ( ( notification.getNotificationAction( ) != null ) && notification.getNotificationAction( ).equals(
TicketsConstants.OFFER_STATUT_CANCEL ) ) )
{
notification.setNotificationAction( TicketsConstants.OFFER_STATUT_CANCEL );
// Set the default recipientsTo
StringBuilder recipientsTo = new StringBuilder( 100 );
for ( ReservationDTO reservationDTO : listReservationsPurchase )
{
recipientsTo.append( reservationDTO.getEmailAgent( ) ).append( AppPropertiesService.getProperty( PROPERTY_MAIL_SEPARATOR ) );
}
notification.setRecipientsTo( recipientsTo.toString( ) );
// Set the default subject
notification
.setSubject( getMessage( MESSAGE_NOTIFICATION_CANCEL_SUBJECT, seance.getProduct( ).getName( ), seance.getDate( ), seance.getHour( ) ) );
// Set the default message
Map<String, Object> modelMail = new HashMap<String, Object>( );
modelMail.put( MARK_BASE_URL, AppPathService.getBaseUrl( request ) );
modelMail.put( MARK_SEANCE, seance );
HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_MAIL_CANCEL, request.getLocale( ), modelMail );
notification.setMessage( template.getHtml( ) );
}
// Action to send notification to partner and lock the offer
else
if ( StringUtils.isNotEmpty( strLock )
|| ( ( notification.getNotificationAction( ) != null ) && notification.getNotificationAction( ).equals(
TicketsConstants.OFFER_STATUT_LOCK ) ) )
{
ShowDTO product = seance.getProduct( );
if ( product != null )
{
Integer idSalle = product.getIdProvider( );
if ( idSalle != null )
{
Integer [ ] arrayIdContact = seance.getIdContact( );
if ( ( arrayIdContact != null ) && ( arrayIdContact.length > 0 ) )
{
PartnerDTO partner = _serviceProvider.findById( idSalle );
StringBuilder contactMail = null;
for ( Integer idContact : arrayIdContact )
{
// Hide empty contact in mailing list
if ( idContact >= 0 )
{
if ( contactMail == null )
{
contactMail = new StringBuilder( );
}
else
{
contactMail.append( ";" );
}
contactMail.append( partner.getContactMail( idContact ) );
}
}
if ( contactMail != null )
{
if ( contactMail.toString( ) != null )
{
notification.setRecipientsTo( contactMail.toString( ) );
}
else
{
notification.setRecipientsTo( "" );
}
}
}
}
}
notification.setNotificationAction( TicketsConstants.OFFER_STATUT_LOCK );
// Set the default recipientsTo
// Set the default subject
notification.setSubject( getMessage( MESSAGE_NOTIFICATION_BOOKING_LIST_SUBJECT, seance.getProduct( ).getName( ) + " " + seance.getDate( )
+ " - " + seance.getHour( ) ) );
// Set the default message
Map<String, Object> modelMail = new HashMap<String, Object>( );
modelMail.put( MARK_BASE_URL, AppPathService.getBaseUrl( request ) );
modelMail.put( MARK_SEANCE, seance );
modelMail.put( MARK_TARIF_REDUIT_ID, TicketsConstants.OFFER_TYPE_REDUCT_ID );
modelMail.put( MARK_LIST_RESERVATION, listReservationsPurchase );
HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_MAIL_LOCK, request.getLocale( ), modelMail );
notification.setMessage( template.getHtml( ) );
}
// Else action to send notification
else
{
// Set the default recipientsTo
StringBuilder recipientsTo = new StringBuilder( );
for ( ReservationDTO purchase : listReservationsPurchase )
{
recipientsTo.append( purchase.getEmailAgent( ) ).append( AppPropertiesService.getProperty( PROPERTY_MAIL_SEPARATOR ) );
}
notification.setRecipientsTo( recipientsTo.toString( ) );
}
}
// If the action is to cancel the offer
if ( StringUtils.isNotEmpty( strCancel )
|| ( ( notification.getNotificationAction( ) != null ) && notification.getNotificationAction( ).equals( TicketsConstants.OFFER_STATUT_CANCEL ) ) )
{
model.put( MARK_AVERTISSEMENT, I18nService.getLocalizedString( MESSAGE_AVERTISSEMENT_CANCEL_OFFER, request.getLocale( ) ) );
}
// Action to send notification to partner and lock the offer
else
if ( StringUtils.isNotEmpty( strLock )
|| ( ( notification.getNotificationAction( ) != null ) && notification.getNotificationAction( ).equals( TicketsConstants.OFFER_STATUT_LOCK ) ) )
{
model.put( MARK_AVERTISSEMENT, I18nService.getLocalizedString( MESSAGE_AVERTISSEMENT_SEND_OFFER, request.getLocale( ) ) );
}
// Add the JSP wich called this action
model.put( StockConstants.MARK_JSP_BACK, request.getParameter( StockConstants.MARK_JSP_BACK ) );
model.put( MARK_NOTIFICATION, notification );
model.put( MARK_TITLE, I18nService.getLocalizedString( PROPERTY_PAGE_TITLE_SEND_NOTIFICATION, Locale.getDefault( ) ) );
if ( StringUtils.isNotEmpty( strCancel ) || StringUtils.isNotEmpty( strNotify ) )
{
if (listReservationsPurchase !=null){
for ( ReservationDTO reservationDTO : listReservationsPurchase )
{
listContact.add( reservationDTO.getEmailAgent( ) );
}
}
}
else
{
List<Contact> lstContact = ofNullable( showDto ).map( e -> _serviceProvider.findById( e.getIdProvider( ) ).getContactList( ) ).orElse( null );
if ( lstContact != null && productById != null )
{
for ( Contact c : lstContact )
{
for ( AbstractAttributeNum sh : productById.getAttributeNumList( ) )
{
if ( sh.getValue( ).intValueExact( ) == c.getId( ) && sh.getKey( ).contains( "idContact" ) )
{
listContact.add( c.getMail( ) );
}
}
}
}
}
model.put( MARK_PARTNER_CONTACT_MAIL, listContact );
HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_SEND_NOTIFICATION, getLocale( ), model );
return getAdminPage( template.getHtml( ) );
}
/**
* Send a notification
*
* @param request
* The HTTP request
* @return redirection url
*/
public String doSendNotification( HttpServletRequest request )
{
if ( null != request.getParameter( StockConstants.PARAMETER_BUTTON_CANCEL ) )
{
return doGoBack( request );
}
NotificationDTO notification = new NotificationDTO( );
populate( notification, request );
try
{
// Controls mandatory fields
validateBilletterie( notification );
if ( ( notification.getIdOffer( ) != null ) && ( notification.getIdOffer( ) > 0 ) )
{
SeanceDTO seance = this._serviceOffer.findSeanceById( notification.getIdOffer( ) );
if ( notification.getNotificationAction( ).equals( TicketsConstants.OFFER_STATUT_LOCK ) )
{
seance.setStatut( TicketsConstants.OFFER_STATUT_LOCK );
this._serviceOffer.update( seance );
}
else
if ( notification.getNotificationAction( ).equals( TicketsConstants.OFFER_STATUT_CANCEL ) )
{
seance.setStatut( TicketsConstants.OFFER_STATUT_CANCEL );
this._serviceOffer.update( seance );
}
}
_serviceNotification.send( notification );
}
catch( FunctionnalException e )
{
return manageFunctionnalException( request, e, JSP_SEND_NOTIFICATION );
}
return doGoBack( request );
}
/**
* Return the url of the JSP which called the last action
*
* @param request
* The Http request
* @return The url of the last JSP
*/
private String doGoBack( HttpServletRequest request )
{
String strJspBack = request.getParameter( StockConstants.MARK_JSP_BACK );
return StringUtils.isNotBlank( strJspBack ) ? ( AppPathService.getBaseUrl( request ) + strJspBack )
: ( AppPathService.getBaseUrl( request ) + JSP_MANAGE_OFFERS );
}
}