/*
* 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.batch.service.impl;
import java.sql.Date;
import java.util.ArrayList;
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.TemParameterConstants;
import org.kuali.kfs.module.tem.batch.TravelImportedExpenseNotificationStep;
import org.kuali.kfs.module.tem.batch.service.TravelImportedExpenseNotificationService;
import org.kuali.kfs.module.tem.businessobject.HistoricalTravelExpense;
import org.kuali.kfs.module.tem.businessobject.TemProfile;
import org.kuali.kfs.module.tem.document.TravelDocument;
import org.kuali.kfs.module.tem.document.service.TravelDocumentService;
import org.kuali.kfs.module.tem.service.HistoricalTravelExpenseService;
import org.kuali.kfs.module.tem.service.TemProfileService;
import org.kuali.kfs.sys.KFSConstants;
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.exception.WorkflowException;
import org.kuali.rice.krad.service.BusinessObjectService;
import org.kuali.rice.krad.service.DocumentService;
import org.kuali.rice.krad.util.ObjectUtils;
import org.springframework.transaction.annotation.Transactional;
public class TravelImportedExpenseNotificationServiceImpl implements TravelImportedExpenseNotificationService {
protected DateTimeService dateTimeService;
protected BusinessObjectService businessObjectService;
protected TemProfileService temProfileService;
protected HistoricalTravelExpenseService historicalTravelExpenseService;
protected TravelDocumentService travelDocumentService;
protected DocumentService documentService;
protected KfsNotificationService kfsNotificationService;
protected ParameterService parameterService;
protected String notificationTemplate;
/**
* @see org.kuali.kfs.module.tem.batch.service.TravelImportedExpenseNotificationService#sendImportedExpenseNotification()
*/
@Override
public void sendImportedExpenseNotification() {
List<HistoricalTravelExpense> travelExpenses = this.getHistoricalTravelExpenseService().getImportedExpesnesToBeNotified();
Map<Integer, List<HistoricalTravelExpense>> expensesGroupByTraveler = this.groupExpensesByTraveler(travelExpenses);
for(Integer travelerProfileId : expensesGroupByTraveler.keySet()){
if (travelerProfileId != null) {
List<HistoricalTravelExpense> expensesOfTraveler = expensesGroupByTraveler.get(travelerProfileId);
if(ObjectUtils.isNotNull(expensesOfTraveler) && !expensesOfTraveler.isEmpty()){
this.sendImportedExpenseNotification(travelerProfileId, expensesOfTraveler);
}
}
}
}
/**
* @see org.kuali.kfs.module.tem.batch.service.TravelImportedExpenseNotificationService#sendImportedExpenseNotification(java.lang.Integer)
*/
@Override
@Transactional
public void sendImportedExpenseNotification(Integer travelerProfileId) {
List<HistoricalTravelExpense> expensesOfTraveler = this.getHistoricalTravelExpenseService().getImportedExpesnesToBeNotified(travelerProfileId);
this.sendImportedExpenseNotification(travelerProfileId, expensesOfTraveler);
}
/**
* @see org.kuali.kfs.module.tem.batch.service.TravelImportedExpenseNotificationService#sendImportedExpenseNotification(java.lang.String, java.util.List)
*/
@Override
@Transactional
public void sendImportedExpenseNotification(Integer travelerProfileId, List<HistoricalTravelExpense> expensesOfTraveler) {
Date notificationDate = this.getDateTimeService().getCurrentSqlDate();
List<HistoricalTravelExpense> expensesOfTravelerImportByTrip = new ArrayList<HistoricalTravelExpense>();
List<HistoricalTravelExpense> expensesOfTravelerImportByTraveler = new ArrayList<HistoricalTravelExpense>();
for(HistoricalTravelExpense expense : expensesOfTraveler){
expense.setExpenseNotificationDate(notificationDate);
String importBy = ObjectUtils.isNotNull(expense.getAgencyStagingData()) ? expense.getAgencyStagingData().getImportBy() : KFSConstants.EMPTY_STRING;
importBy = ObjectUtils.isNotNull(expense.getCreditCardStagingData()) ? expense.getCreditCardStagingData().getImportBy() : KFSConstants.EMPTY_STRING;
if(TemConstants.ExpenseImportTypes.IMPORT_BY_TRIP.equals(importBy)) {
expensesOfTravelerImportByTrip.add(expense);
}
else {
expensesOfTravelerImportByTraveler.add(expense);
}
this.getBusinessObjectService().save(expense);
}
if(!expensesOfTravelerImportByTrip.isEmpty()) {
MailMessage mailMessageByTrip = this.buildExpenseNotificationMailMessage(travelerProfileId, expensesOfTravelerImportByTrip, TemConstants.ExpenseImportTypes.IMPORT_BY_TRIP);
this.getKfsNotificationService().sendNotificationByMail(mailMessageByTrip);
}
if(!expensesOfTravelerImportByTraveler.isEmpty()) {
MailMessage mailMessageByTraveler = this.buildExpenseNotificationMailMessage(travelerProfileId, expensesOfTravelerImportByTraveler, TemConstants.ExpenseImportTypes.IMPORT_BY_TRAVELLER);
this.getKfsNotificationService().sendNotificationByMail(mailMessageByTraveler);
}
}
protected MailMessage buildExpenseNotificationMailMessage(Integer travelerProfileId, List<HistoricalTravelExpense> expensesOfTraveler, String importBy) {
MailMessage mailMessage = new MailMessage();
String senderEmailAddress = this.getNotificationSender();
mailMessage.setFromAddress(senderEmailAddress);
TemProfile travelerProfile = this.getTemProfileService().findTemProfileById(travelerProfileId);
String travelerEmailAddress = travelerProfile.getEmailAddress();
mailMessage.addToAddress(travelerEmailAddress);
String notificationSubject = this.getNotificationSubject();
mailMessage.setSubject(this.getNotificationSubject());
String notificationBody = this.buildNotificationBody(travelerProfile, expensesOfTraveler, importBy);
mailMessage.setMessage(notificationBody);
return mailMessage;
}
/**
* collect all the information from the given customer invoice document and build the notification body
*/
protected String buildNotificationBody(TemProfile travelerProfile, List<HistoricalTravelExpense> expensesOfTraveler, String importBy) {
Map<String, Object> notificationInformationHolder = new HashMap<String, Object>();
notificationInformationHolder.put(TemConstants.TRAVELER_PROFILE_KEY, travelerProfile);
notificationInformationHolder.put(TemConstants.TRAVEL_EXPENSES_KEY, expensesOfTraveler);
notificationInformationHolder.put(KFSConstants.NOTIFICATION_TEXT_KEY, this.getNotificationText(importBy));
return this.getKfsNotificationService().generateNotificationContent(this.getNotificationTemplate(), notificationInformationHolder);
}
protected Map<Integer, List<HistoricalTravelExpense>> groupExpensesByTraveler(List<HistoricalTravelExpense> travelExpenses) {
Map<Integer, List<HistoricalTravelExpense>> expensesGroupedByTraveler = new HashMap<Integer, List<HistoricalTravelExpense>>();
for(HistoricalTravelExpense expense : travelExpenses){
Integer profileId = expense.getProfileId();
if (profileId == null) {
profileId = lookupProfileId(expense);
}
if(expensesGroupedByTraveler.containsKey(profileId)){
List<HistoricalTravelExpense> expensesOfTraveler = expensesGroupedByTraveler.get(profileId);
expensesOfTraveler.add(expense);
}
else{
List<HistoricalTravelExpense> expensesOfTraveler = new ArrayList<HistoricalTravelExpense>();
expensesOfTraveler.add(expense);
expensesGroupedByTraveler.put(profileId, expensesOfTraveler);
}
}
return expensesGroupedByTraveler;
}
/**
* Uses the given reconciled expense to look up the profile id (presumably from the trip's current document)
* @param reconciledExpense the reconciled expense to try to find a profile id for
* @return the profile id for the expense, or null if one could not be determined
*/
protected Integer lookupProfileId(HistoricalTravelExpense reconciledExpense) {
if (reconciledExpense.getProfileId() != null) {
return reconciledExpense.getProfileId();
}
if (!StringUtils.isBlank(reconciledExpense.getDocumentNumber())) {
try {
final TravelDocument travelDoc = (TravelDocument)getDocumentService().getByDocumentHeaderIdSessionless(reconciledExpense.getDocumentNumber());
if (travelDoc != null && !ObjectUtils.isNull(travelDoc.getTemProfileId())) {
return travelDoc.getTemProfileId();
}
}
catch (WorkflowException we) {
// i can't access a document in workflow? Then let's blow chunks, fun style!
throw new RuntimeException("Cannot retrieve document #"+reconciledExpense.getDocumentNumber()+"...and really, I'm just trying to look up a traveler is all", we);
}
}
if (!StringUtils.isBlank(reconciledExpense.getTripId())) {
final TravelDocument travelDoc = getTravelDocumentService().getParentTravelDocument(reconciledExpense.getTripId());
if (travelDoc != null && !ObjectUtils.isNull(travelDoc.getTemProfileId())) {
return travelDoc.getTemProfileId();
}
}
return null;
}
protected List<HistoricalTravelExpense> getImportedExpesnesToBeNotified() {
return null;
}
/**
* 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() {
return this.getParameterService().getParameterValueAsString(TravelImportedExpenseNotificationStep.class, TemConstants.ImportedExpenseParameter.NOTIFICATION_SUBJECT_PARAM_NAME);
}
/**
* get the notification text from an application parameter
*/
protected String getNotificationText(String importBy) {
String parameterName = TemConstants.ExpenseImportTypes.IMPORT_BY_TRIP.equals(importBy) ? TemConstants.ImportedExpenseParameter.NOTIFICATION_TEXT_BY_TRP_PARAM_NAME :TemConstants.ImportedExpenseParameter.NOTIFICATION_TEXT_BY_TRV_PARAM_NAME;
String notificationText = this.getParameterService().getParameterValueAsString(TravelImportedExpenseNotificationStep.class, parameterName );
return notificationText;
}
/**
* Gets the temProfileService attribute.
* @return Returns the temProfileService.
*/
public TemProfileService getTemProfileService() {
return temProfileService;
}
/**
* Sets the temProfileService attribute value.
* @param temProfileService The temProfileService to set.
*/
public void setTemProfileService(TemProfileService temProfileService) {
this.temProfileService = temProfileService;
}
/**
* 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;
}
/**
* 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 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 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 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 historicalTravelExpenseService attribute.
* @return Returns the historicalTravelExpenseService.
*/
public HistoricalTravelExpenseService getHistoricalTravelExpenseService() {
return historicalTravelExpenseService;
}
/**
* Sets the historicalTravelExpenseService attribute value.
* @param historicalTravelExpenseService The historicalTravelExpenseService to set.
*/
public void setHistoricalTravelExpenseService(HistoricalTravelExpenseService historicalTravelExpenseService) {
this.historicalTravelExpenseService = historicalTravelExpenseService;
}
public TravelDocumentService getTravelDocumentService() {
return travelDocumentService;
}
public void setTravelDocumentService(TravelDocumentService travelDocumentService) {
this.travelDocumentService = travelDocumentService;
}
public DocumentService getDocumentService() {
return documentService;
}
public void setDocumentService(DocumentService documentService) {
this.documentService = documentService;
}
}