/* * The Kuali Financial System, a comprehensive financial management system for higher education. * * Copyright 2005-2014 The Kuali Foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.kuali.kfs.module.tem.service.impl; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.kuali.kfs.module.tem.TemConstants; import org.kuali.kfs.module.tem.TemConstants.NotificationPreference; import org.kuali.kfs.module.tem.TemParameterConstants; import org.kuali.kfs.module.tem.TemPropertyConstants; import org.kuali.kfs.module.tem.businessobject.TemProfile; import org.kuali.kfs.module.tem.businessobject.TravelerDetail; import org.kuali.kfs.module.tem.document.TravelAuthorizationDocument; import org.kuali.kfs.module.tem.document.TravelDocument; import org.kuali.kfs.module.tem.service.TemProfileService; import org.kuali.kfs.module.tem.service.TravelDocumentNotificationService; import org.kuali.kfs.sys.KFSPropertyConstants; import org.kuali.kfs.sys.context.SpringContext; import org.kuali.kfs.sys.service.KfsNotificationService; import org.kuali.rice.core.api.datetime.DateTimeService; import org.kuali.rice.core.api.mail.MailMessage; import org.kuali.rice.coreservice.framework.parameter.ParameterService; import org.kuali.rice.kew.api.KewApiConstants; import org.kuali.rice.kew.api.document.DocumentStatus; import org.kuali.rice.kew.framework.postprocessor.DocumentRouteStatusChange; import org.kuali.rice.krad.service.BusinessObjectService; import org.kuali.rice.krad.util.ObjectUtils; /** * implement the notification to the traveler based on the email preferences stored in the traveler profile */ public class TravelDocumentNotificationServiceImpl implements TravelDocumentNotificationService { protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(TravelDocumentNotificationServiceImpl.class); private String notificationTemplate; private ParameterService parameterService; private KfsNotificationService kfsNotificationService; private BusinessObjectService businessObjectService; private DateTimeService dateTimeService; private List<String> noNotificationRouteStatusList; /** * @see org.kuali.kfs.module.tem.service.TravelDocumentNotificationService#sendNotificationOnChange(org.kuali.kfs.module.tem.document.TravelDocument, * org.kuali.rice.kew.dto.DocumentRouteStatusChange) */ @Override public void sendNotificationOnChange(TravelDocument travelDocument, DocumentRouteStatusChange statusChangeDTO) { String documentTypeCode = travelDocument.getDocumentHeader().getWorkflowDocument().getDocumentTypeName(); NotificationPreference preference = null; if (this.isNotificationEnabled()) { TemProfile travelProfile = this.getTravelProfile(travelDocument); String newRouteStatus = statusChangeDTO.getNewRouteStatus(); if (travelProfile == null) { LOG.error("travelProfile is null."); return; } if (travelDocument instanceof TravelAuthorizationDocument) { if (!verifyDocumentTypeCodes(documentTypeCode, this.getEligibleTravelAuthorizationDocumentTypeCodes())) { return; } preference = getEmailNotificationPreference(preference, newRouteStatus, travelProfile.getNotifyTAFinal(), travelProfile.getNotifyTAStatusChange(), documentTypeCode); } else { // TR/ENT/RELO if (!verifyDocumentTypeCodes(documentTypeCode, this.getEligibleTravelExpenseDocumentTypeCodes())) { return; } preference = getEmailNotificationPreference(preference, newRouteStatus, travelProfile.getNotifyTERFinal(), travelProfile.getNotifyTERStatusChange(), documentTypeCode); } this.sendNotificationByPreference(travelDocument, statusChangeDTO, preference); } } private boolean verifyDocumentTypeCodes(String documentTypeCode, Collection<String> eligibleDocumentTypeCodes) { if (ObjectUtils.isNull(eligibleDocumentTypeCodes) || !eligibleDocumentTypeCodes.contains(documentTypeCode)) { return false; } return true; } private NotificationPreference getEmailNotificationPreference(NotificationPreference preference, String newRouteStatus, boolean notifyOnFinal, boolean notifyOnStatusChange, String documentTypeCode) { if (notifyOnFinal && (DocumentStatus.FINAL.getCode().equals(newRouteStatus) || DocumentStatus.PROCESSED.getCode().equals(newRouteStatus))) { preference = TemConstants.TravelDocTypes.TRAVEL_AUTHORIZATION_DOCUMENT.equals(documentTypeCode) ? NotificationPreference.TA_ON_FINAL : NotificationPreference.TER_ON_FINAL; } else if (notifyOnStatusChange && !this.getNoNotificationRouteStatusList().contains(newRouteStatus)) { preference = TemConstants.TravelDocTypes.TRAVEL_AUTHORIZATION_DOCUMENT.equals(documentTypeCode) ? NotificationPreference.TA_ON_CHANGE : NotificationPreference.TER_ON_CHANGE; } return preference; } /** * get the traveler profile associated with the given travel document */ protected TemProfile getTravelProfile(TravelDocument travelDocument) { Integer travelProfileId = travelDocument.getProfileId(); if (travelProfileId != null) { return this.getBusinessObjectService().findBySinglePrimaryKey(TemProfile.class, travelProfileId); } return null; } /** * send notification based on the given document and preference */ protected void sendNotificationByPreference(TravelDocument travelDocument, DocumentRouteStatusChange statusChangeDTO, NotificationPreference preference) { if (ObjectUtils.isNull(preference)) { return; } MailMessage mailMessage = this.buildDocumentStatusChangeMailMessage(travelDocument, statusChangeDTO, preference); if (mailMessage != null) { this.getKfsNotificationService().sendNotificationByMail(mailMessage); } else { LOG.error("mailMessage is null."); } } /** * build mail message object from the given travel document */ @SuppressWarnings("null") protected MailMessage buildDocumentStatusChangeMailMessage(TravelDocument travelDocument, DocumentRouteStatusChange statusChangeDTO, NotificationPreference preference) { MailMessage mailMessage = new MailMessage(); String senderEmailAddress = this.getNotificationSender(); mailMessage.setFromAddress(senderEmailAddress); TravelerDetail traveler = travelDocument.getTraveler(); String travelerEmailAddress = null; if (!ObjectUtils.isNull(traveler) && !ObjectUtils.isNull(travelDocument.getProfileId())) { TemProfile profile = SpringContext.getBean(TemProfileService.class).findTemProfileById(travelDocument.getProfileId()); travelerEmailAddress = profile.getEmailAddress(); }else{ travelerEmailAddress = traveler.getEmailAddress(); } if (senderEmailAddress != null && travelerEmailAddress != null) { mailMessage.addToAddress(travelerEmailAddress); String notificationSubject = this.getNotificationSubject(preference); mailMessage.setSubject(notificationSubject); String notificationBody = this.buildNotificationBody(travelDocument, statusChangeDTO, preference); mailMessage.setMessage(notificationBody); return mailMessage; } return null; } /** * collect all the information and build the notification body */ protected String buildNotificationBody(TravelDocument travelDocument, DocumentRouteStatusChange statusChange, NotificationPreference preference) { Map<String, Object> notificationInformationHolder = new HashMap<String, Object>(); notificationInformationHolder.put(TemConstants.NOTIFICATION_PREFERENCE, preference.getLabel()); notificationInformationHolder.put(KFSPropertyConstants.DOCUMENT, travelDocument); notificationInformationHolder.put(TemConstants.STATUS_CHANGE_DTO, statusChange); String newStatusLabel = KewApiConstants.DOCUMENT_STATUSES.get(statusChange.getNewRouteStatus()); notificationInformationHolder.put(TemPropertyConstants.NEW_ROUTE_STATUS, newStatusLabel); String oldStatusLabel = KewApiConstants.DOCUMENT_STATUSES.get(statusChange.getOldRouteStatus()); notificationInformationHolder.put(TemPropertyConstants.OLD_ROUTE_STATUS, oldStatusLabel); String campusTravelEmailAddress = this.getCampusTravelEmailAddress(); notificationInformationHolder.put(TemConstants.CAMPUS_TRAVEL_EMAIL_ADDRESS, campusTravelEmailAddress); notificationInformationHolder.put(DateTimeService.class.getSimpleName(), dateTimeService); return this.getKfsNotificationService().generateNotificationContent(this.getNotificationTemplate(), notificationInformationHolder); } /** * get the eligible travel expense document type codes for notification from an application parameter */ protected Collection<String> getEligibleTravelExpenseDocumentTypeCodes() { return this.getParameterService().getParameterValuesAsString(TemParameterConstants.TEM_DOCUMENT.class, TemConstants.TravelParameters.SEND_NOTIFICATION_DOCUMENT_TYPES); } /** * get the eligible TA document type codes for notification from an application parameter */ protected Collection<String> getEligibleTravelAuthorizationDocumentTypeCodes() { return this.getParameterService().getParameterValuesAsString(TravelAuthorizationDocument.class, TemConstants.TravelParameters.SEND_NOTIFICATION_DOCUMENT_TYPES); } /** * get the email notification sender from an application parameter */ protected String getNotificationSender() { return this.getParameterService().getParameterValueAsString(TemParameterConstants.TEM_ALL.class, TemConstants.TravelParameters.FROM_EMAIL_ADDRESS_PARAM_NAME); } /** * get the notification subject from an application parameter */ protected String getNotificationSubject(NotificationPreference preference) { final String preferenceCode = preference.getParameterEventCode(); final String subjectParameterName = StringUtils.isBlank(preferenceCode) ? TemConstants.TravelParameters.CHANGE_NOTIFICATION_SUBJECT : preferenceCode + "_NOTIFICATION_SUBJECT"; final Class<?> subjectParameterComponent = preference.getParameterComponentClass() == null ? TemParameterConstants.TEM_DOCUMENT.class : preference.getParameterComponentClass(); return this.getParameterService().getParameterValueAsString(subjectParameterComponent, subjectParameterName); } /** * get the Campus Travel Email Address from an application parameter */ protected String getCampusTravelEmailAddress() { return this.getParameterService().getParameterValueAsString(TemParameterConstants.TEM_DOCUMENT.class, TemConstants.TravelParameters.TRAVEL_EMAIL_ADDRESS); } /** * determine whether the notification is enable or not */ protected boolean isNotificationEnabled() { return this.getParameterService().getParameterValueAsBoolean(TemParameterConstants.TEM_DOCUMENT.class, TemConstants.TravelParameters.SEND_NOTIFICATION_ON_WORKFLOW_STATUS_CHANGE_IND); } /** * Gets the noNotificationRouteStatusList attribute. * @return Returns the noNotificationRouteStatusList. */ protected List<String> getNoNotificationRouteStatusList() { if(ObjectUtils.isNull(noNotificationRouteStatusList)){ noNotificationRouteStatusList = new ArrayList<String>(); noNotificationRouteStatusList.add(DocumentStatus.PROCESSED.getCode()); noNotificationRouteStatusList.add(DocumentStatus.INITIATED.getCode()); noNotificationRouteStatusList.add(DocumentStatus.SAVED.getCode()); } return noNotificationRouteStatusList; } /** * Gets the parameterService attribute. * * @return Returns the parameterService. */ public ParameterService getParameterService() { return parameterService; } /** * Sets the parameterService attribute value. * * @param parameterService The parameterService to set. */ public void setParameterService(ParameterService parameterService) { this.parameterService = parameterService; } /** * Gets the kfsNotificationService attribute. * * @return Returns the kfsNotificationService. */ public KfsNotificationService getKfsNotificationService() { return kfsNotificationService; } /** * Sets the kfsNotificationService attribute value. * * @param kfsNotificationService The kfsNotificationService to set. */ public void setKfsNotificationService(KfsNotificationService kfsNotificationService) { this.kfsNotificationService = kfsNotificationService; } /** * Gets the notificationTemplate attribute. * * @return Returns the notificationTemplate. */ public String getNotificationTemplate() { return notificationTemplate; } /** * Sets the notificationTemplate attribute value. * * @param notificationTemplate The notificationTemplate to set. */ public void setNotificationTemplate(String notificationTemplate) { this.notificationTemplate = notificationTemplate; } /** * Gets the businessObjectService attribute. * @return Returns the businessObjectService. */ public BusinessObjectService getBusinessObjectService() { return businessObjectService; } /** * Sets the businessObjectService attribute value. * @param businessObjectService The businessObjectService to set. */ public void setBusinessObjectService(BusinessObjectService businessObjectService) { this.businessObjectService = businessObjectService; } /** * Gets the dateTimeService attribute. * @return Returns the dateTimeService. */ public DateTimeService getDateTimeService() { return dateTimeService; } /** * Sets the dateTimeService attribute value. * @param dateTimeService The dateTimeService to set. */ public void setDateTimeService(DateTimeService dateTimeService) { this.dateTimeService = dateTimeService; } }