001 /*
002 * Copyright 2011 The Kuali Foundation.
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.kfs.pdp.service.impl;
017
018 import java.text.MessageFormat;
019 import java.util.Arrays;
020 import java.util.Collections;
021 import java.util.Date;
022 import java.util.HashSet;
023 import java.util.List;
024 import java.util.Map;
025
026 import org.apache.commons.lang.StringUtils;
027 import org.kuali.kfs.pdp.PdpKeyConstants;
028 import org.kuali.kfs.pdp.PdpParameterConstants;
029 import org.kuali.kfs.pdp.PdpPropertyConstants;
030 import org.kuali.kfs.pdp.batch.ExtractAchPaymentsStep;
031 import org.kuali.kfs.pdp.batch.LoadPaymentsStep;
032 import org.kuali.kfs.pdp.businessobject.ACHBank;
033 import org.kuali.kfs.pdp.businessobject.Batch;
034 import org.kuali.kfs.pdp.businessobject.CustomerProfile;
035 import org.kuali.kfs.pdp.businessobject.PaymentDetail;
036 import org.kuali.kfs.pdp.businessobject.PaymentFileLoad;
037 import org.kuali.kfs.pdp.businessobject.PaymentGroup;
038 import org.kuali.kfs.pdp.businessobject.PaymentNoteText;
039 import org.kuali.kfs.pdp.service.AchBankService;
040 import org.kuali.kfs.pdp.service.CustomerProfileService;
041 import org.kuali.kfs.pdp.service.PdpEmailService;
042 import org.kuali.kfs.sys.KFSConstants;
043 import org.kuali.kfs.sys.KFSPropertyConstants;
044 import org.kuali.kfs.sys.service.impl.KfsParameterConstants;
045 import org.kuali.rice.kim.bo.Person;
046 import org.kuali.rice.kns.mail.InvalidAddressException;
047 import org.kuali.rice.kns.mail.MailMessage;
048 import org.kuali.rice.kns.service.DataDictionaryService;
049 import org.kuali.rice.kns.service.KualiConfigurationService;
050 import org.kuali.rice.kns.service.MailService;
051 import org.kuali.rice.kns.service.ParameterService;
052 import org.kuali.rice.kns.util.ErrorMessage;
053 import org.kuali.rice.kns.util.KualiDecimal;
054 import org.kuali.rice.kns.util.MessageMap;
055 import org.kuali.rice.kns.web.format.CurrencyFormatter;
056 import org.kuali.rice.kns.web.format.Formatter;
057
058 /**
059 * @see org.kuali.kfs.pdp.service.PdpEmailService
060 */
061 public class PdpEmailServiceImpl implements PdpEmailService {
062 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PdpEmailServiceImpl.class);
063
064 private CustomerProfileService customerProfileService;
065 private KualiConfigurationService kualiConfigurationService;
066 protected MailService mailService;
067 protected ParameterService parameterService;
068 private DataDictionaryService dataDictionaryService;
069 private AchBankService achBankService;
070
071 /**
072 * @see org.kuali.kfs.pdp.service.PdpEmailService#sendErrorEmail(org.kuali.kfs.pdp.businessobject.PaymentFileLoad,
073 * org.kuali.rice.kns.util.ErrorMap)
074 */
075 public void sendErrorEmail(PaymentFileLoad paymentFile, MessageMap errors) {
076 LOG.debug("sendErrorEmail() starting");
077
078 // check email configuration
079 if (!isPaymentEmailEnabled()) {
080 return;
081 }
082
083 MailMessage message = new MailMessage();
084
085 message.setFromAddress(mailService.getBatchMailingList());
086 message.setSubject(getEmailSubject(PdpParameterConstants.PAYMENT_LOAD_FAILURE_EMAIL_SUBJECT_PARAMETER_NAME));
087
088 StringBuffer body = new StringBuffer();
089 List<String> ccAddresses = parameterService.getParameterValues(LoadPaymentsStep.class, PdpParameterConstants.HARD_EDIT_CC);
090
091 if (paymentFile == null) {
092 if (ccAddresses.isEmpty()) {
093 LOG.error("sendErrorEmail() No HARD_EDIT_CC addresses. No email sent");
094 return;
095 }
096
097 message.getToAddresses().addAll(ccAddresses);
098
099 body.append(getMessage(PdpKeyConstants.MESSAGE_PAYMENT_EMAIL_BAD_FILE_PARSE) + "\n\n");
100 }
101 else {
102 CustomerProfile customer = customerProfileService.get(paymentFile.getChart(), paymentFile.getUnit(), paymentFile.getSubUnit());
103 if (customer == null) {
104 LOG.error("sendErrorEmail() Invalid Customer. Sending email to CC addresses");
105
106 if (ccAddresses.isEmpty()) {
107 LOG.error("sendErrorEmail() No HARD_EDIT_CC addresses. No email sent");
108 return;
109 }
110
111 message.getToAddresses().addAll(ccAddresses);
112
113 body.append(getMessage(PdpKeyConstants.MESSAGE_PAYMENT_EMAIL_INVALID_CUSTOMER) + "\n\n");
114 }
115 else {
116 String toAddresses = StringUtils.deleteWhitespace(customer.getProcessingEmailAddr());
117 List<String> toAddressList = Arrays.asList(toAddresses.split(","));
118
119 message.getToAddresses().addAll(toAddressList);
120 message.getCcAddresses().addAll(ccAddresses);
121 //TODO: for some reason the mail service does not work unless the bcc list has addresss. This is a temporary workaround
122 message.getBccAddresses().addAll(ccAddresses);
123 }
124 }
125
126 if (paymentFile != null) {
127 body.append(getMessage(PdpKeyConstants.MESSAGE_PAYMENT_EMAIL_FILE_NOT_LOADED) + "\n\n");
128 addPaymentFieldsToBody(body, null, paymentFile.getChart(), paymentFile.getUnit(), paymentFile.getSubUnit(), paymentFile.getCreationDate(), paymentFile.getPaymentCount(), paymentFile.getPaymentTotalAmount());
129 }
130
131 body.append("\n" + getMessage(PdpKeyConstants.MESSAGE_PAYMENT_EMAIL_ERROR_MESSAGES) + "\n");
132 List<ErrorMessage> errorMessages = errors.getMessages(KFSConstants.GLOBAL_ERRORS);
133 for (ErrorMessage errorMessage : errorMessages) {
134 body.append(getMessage(errorMessage.getErrorKey(), (Object[]) errorMessage.getMessageParameters()) + "\n\n");
135 }
136
137 message.setMessage(body.toString());
138
139 // KFSMI-6475 - if not a production instance, replace the recipients with the testers list
140 alterMessageWhenNonProductionInstance(message, null);
141
142 try {
143 mailService.sendMessage(message);
144 } catch (InvalidAddressException e) {
145 LOG.error("sendErrorEmail() Invalid email address. Message not sent", e);
146 }
147 }
148
149 /**
150 * KFSMI-6475 - Alter the subject and switch all recipients
151 *
152 * @param message
153 * @param environmentCode
154 */
155 @SuppressWarnings("rawtypes")
156 public void alterMessageWhenNonProductionInstance( MailMessage message, String environmentCode ) {
157 if ( !kualiConfigurationService.isProductionEnvironment() ) {
158 if ( environmentCode == null ) {
159 environmentCode = kualiConfigurationService.getPropertyString(KFSConstants.ENVIRONMENT_KEY);
160 }
161 // Add the environment code to the subject
162 message.setSubject(environmentCode + ": " + message.getSubject());
163 // insert the original recipients into the beginning of the message
164 StringBuffer recipients = new StringBuffer();
165 recipients.append("To : ").append(message.getToAddresses().toString()).append('\n');
166 recipients.append("Cc : ").append(message.getCcAddresses().toString()).append('\n');
167 recipients.append("Bcc: ").append(message.getBccAddresses().toString()).append('\n');
168 recipients.append('\n');
169 message.setMessage( recipients.toString() + message.getMessage() );
170 // Clear out the recipients
171 message.setToAddresses(new HashSet());
172 message.setCcAddresses(Collections.emptySet());
173 message.setBccAddresses(Collections.emptySet());
174 // Set all to the batch mailing list
175 message.addToAddress(mailService.getBatchMailingList());
176 }
177 }
178
179 /**
180 * @see org.kuali.kfs.pdp.service.PdpEmailService#sendLoadEmail(org.kuali.kfs.pdp.businessobject.PaymentFileLoad,
181 * java.util.List)
182 */
183 public void sendLoadEmail(PaymentFileLoad paymentFile, List<String> warnings) {
184 LOG.debug("sendLoadEmail() starting");
185
186 // check email configuration
187 if (!isPaymentEmailEnabled()) {
188 return;
189 }
190
191 MailMessage message = new MailMessage();
192
193 message.setFromAddress(mailService.getBatchMailingList());
194 message.setSubject(getEmailSubject(PdpParameterConstants.PAYMENT_LOAD_SUCCESS_EMAIL_SUBJECT_PARAMETER_NAME));
195
196 List<String> ccAddresses = parameterService.getParameterValues(LoadPaymentsStep.class, PdpParameterConstants.HARD_EDIT_CC);
197 message.getCcAddresses().addAll(ccAddresses);
198 message.getBccAddresses().addAll(ccAddresses);
199
200 CustomerProfile customer = customerProfileService.get(paymentFile.getChart(), paymentFile.getUnit(), paymentFile.getSubUnit());
201 String toAddresses = StringUtils.deleteWhitespace(customer.getProcessingEmailAddr());
202 List<String> toAddressList = Arrays.asList(toAddresses.split(","));
203
204 message.getToAddresses().addAll(toAddressList);
205
206 StringBuffer body = new StringBuffer();
207 body.append(getMessage(PdpKeyConstants.MESSAGE_PAYMENT_EMAIL_FILE_LOADED) + "\n\n");
208 addPaymentFieldsToBody(body, paymentFile.getBatchId().intValue(), paymentFile.getChart(), paymentFile.getUnit(), paymentFile.getSubUnit(), paymentFile.getCreationDate(), paymentFile.getPaymentCount(), paymentFile.getPaymentTotalAmount());
209
210 body.append("\n" + getMessage(PdpKeyConstants.MESSAGE_PAYMENT_EMAIL_WARNING_MESSAGES) + "\n");
211 for (String warning : warnings) {
212 body.append(warning + "\n\n");
213 }
214
215 message.setMessage(body.toString());
216
217 // KFSMI-6475 - if not a production instance, replace the recipients with the testers list
218 alterMessageWhenNonProductionInstance(message, null);
219
220 try {
221 mailService.sendMessage(message);
222 }
223 catch (InvalidAddressException e) {
224 LOG.error("sendErrorEmail() Invalid email address. Message not sent", e);
225 }
226
227 if (paymentFile.isFileThreshold()) {
228 sendThresholdEmail(true, paymentFile, customer);
229 }
230
231 if (paymentFile.isDetailThreshold()) {
232 sendThresholdEmail(false, paymentFile, customer);
233 }
234 }
235
236 /**
237 * Sends email for a payment that was over the customer file threshold or the detail threshold
238 *
239 * @param fileThreshold indicates whether the file threshold (true) was violated or the detail threshold (false)
240 * @param paymentFile parsed payment file object
241 * @param customer payment customer
242 */
243 protected void sendThresholdEmail(boolean fileThreshold, PaymentFileLoad paymentFile, CustomerProfile customer) {
244 MailMessage message = new MailMessage();
245
246 message.setFromAddress(mailService.getBatchMailingList());
247 message.setSubject(getEmailSubject(PdpParameterConstants.PAYMENT_LOAD_THRESHOLD_EMAIL_SUBJECT_PARAMETER_NAME));
248
249 StringBuffer body = new StringBuffer();
250
251 body.append(getMessage(PdpKeyConstants.MESSAGE_PAYMENT_EMAIL_FILE_LOADED) + "\n\n");
252 addPaymentFieldsToBody(body, paymentFile.getBatchId().intValue(), paymentFile.getChart(), paymentFile.getUnit(), paymentFile.getSubUnit(), paymentFile.getCreationDate(), paymentFile.getPaymentCount(), paymentFile.getPaymentTotalAmount());
253
254 if (fileThreshold) {
255 String toAddresses = StringUtils.deleteWhitespace(customer.getFileThresholdEmailAddress());
256 List<String> toAddressList = Arrays.asList(toAddresses.split(","));
257
258 message.getToAddresses().addAll(toAddressList);
259 body.append("\n" + getMessage(PdpKeyConstants.MESSAGE_PAYMENT_EMAIL_FILE_THRESHOLD, paymentFile.getPaymentTotalAmount(), customer.getFileThresholdAmount()));
260 }
261 else {
262 String toAddresses = StringUtils.deleteWhitespace(customer.getPaymentThresholdEmailAddress());
263 List<String> toAddressList = Arrays.asList(toAddresses.split(","));
264
265 message.getToAddresses().addAll(toAddressList);
266
267 body.append("\n" + getMessage(PdpKeyConstants.MESSAGE_PAYMENT_EMAIL_DETAIL_THRESHOLD, customer.getPaymentThresholdAmount()) + "\n\n");
268 for (PaymentDetail paymentDetail : paymentFile.getThresholdPaymentDetails()) {
269 paymentDetail.refresh();
270 body.append(getMessage(PdpKeyConstants.MESSAGE_PAYMENT_EMAIL_FILE_THRESHOLD, paymentDetail.getPaymentGroup().getPayeeName(), paymentDetail.getNetPaymentAmount()) + "\n");
271 }
272 }
273
274 List<String> ccAddresses = parameterService.getParameterValues(LoadPaymentsStep.class, PdpParameterConstants.HARD_EDIT_CC);
275 message.getCcAddresses().addAll(ccAddresses);
276 message.getBccAddresses().addAll(ccAddresses);
277
278 message.setMessage(body.toString());
279
280 // KFSMI-6475 - if not a production instance, replace the recipients with the testers list
281 alterMessageWhenNonProductionInstance(message, null);
282
283 try {
284 mailService.sendMessage(message);
285 }
286 catch (InvalidAddressException e) {
287 LOG.error("sendErrorEmail() Invalid email address. Message not sent", e);
288 }
289 }
290
291 /**
292 * @see org.kuali.kfs.pdp.service.PdpEmailService#sendTaxEmail(org.kuali.kfs.pdp.businessobject.PaymentFileLoad)
293 */
294 public void sendTaxEmail(PaymentFileLoad paymentFile) {
295 LOG.debug("sendTaxEmail() starting");
296
297 MailMessage message = new MailMessage();
298
299 message.setFromAddress(mailService.getBatchMailingList());
300 message.setSubject(getEmailSubject(PdpParameterConstants.PAYMENT_LOAD_TAX_EMAIL_SUBJECT_PARAMETER_NAME));
301
302 StringBuffer body = new StringBuffer();
303
304 String taxEmail = parameterService.getParameterValue(KfsParameterConstants.PRE_DISBURSEMENT_ALL.class, PdpParameterConstants.TAX_GROUP_EMAIL_ADDRESS);
305 if (StringUtils.isBlank(taxEmail)) {
306 LOG.error("No Tax E-mail Application Setting found to send notification e-mail");
307 return;
308 }
309 else {
310 message.addToAddress(taxEmail);
311 }
312 List<String> ccAddresses = parameterService.getParameterValues(LoadPaymentsStep.class, PdpParameterConstants.HARD_EDIT_CC);
313 message.getCcAddresses().addAll(ccAddresses);
314 message.getBccAddresses().addAll(ccAddresses);
315
316 body.append(getMessage(PdpKeyConstants.MESSAGE_PAYMENT_EMAIL_FILE_TAX_LOADED) + "\n\n");
317 addPaymentFieldsToBody(body, paymentFile.getBatchId().intValue(), paymentFile.getChart(), paymentFile.getUnit(), paymentFile.getSubUnit(), paymentFile.getCreationDate(), paymentFile.getPaymentCount(), paymentFile.getPaymentTotalAmount());
318
319 body.append("\n" + getMessage(PdpKeyConstants.MESSAGE_PAYMENT_EMAIL_GO_TO_PDP) + "\n");
320
321 message.setMessage(body.toString());
322
323 // KFSMI-6475 - if not a production instance, replace the recipients with the testers list
324 alterMessageWhenNonProductionInstance(message, null);
325
326 try {
327 mailService.sendMessage(message);
328 }
329 catch (InvalidAddressException e) {
330 LOG.error("sendErrorEmail() Invalid email address. Message not sent", e);
331 }
332 }
333
334 /**
335 * @see org.kuali.kfs.pdp.service.PdpEmailService#sendLoadEmail(org.kuali.kfs.pdp.businessobject.Batch)
336 */
337 public void sendLoadEmail(Batch batch) {
338 LOG.debug("sendLoadEmail() starting");
339
340 // check email configuration
341 if (!isPaymentEmailEnabled()) {
342 return;
343 }
344
345 MailMessage message = new MailMessage();
346
347 message.setFromAddress(mailService.getBatchMailingList());
348 message.setSubject(getEmailSubject(PdpParameterConstants.PAYMENT_LOAD_SUCCESS_EMAIL_SUBJECT_PARAMETER_NAME));
349
350 StringBuffer body = new StringBuffer();
351
352 List<String> ccAddresses = parameterService.getParameterValues(LoadPaymentsStep.class, PdpParameterConstants.HARD_EDIT_CC);
353 message.getCcAddresses().addAll(ccAddresses);
354 message.getBccAddresses().addAll(ccAddresses);
355
356 CustomerProfile customer = batch.getCustomerProfile();
357 String toAddresses = StringUtils.deleteWhitespace(customer.getProcessingEmailAddr());
358 List<String> toAddressList = Arrays.asList(toAddresses.split(","));
359
360 message.getToAddresses().addAll(toAddressList);
361
362 body.append(getMessage(PdpKeyConstants.MESSAGE_PAYMENT_EMAIL_FILE_LOADED) + "\n\n");
363 addPaymentFieldsToBody(body, batch.getId().intValue(), customer.getChartCode(), customer.getUnitCode(), customer.getSubUnitCode(), batch.getCustomerFileCreateTimestamp(), batch.getPaymentCount().intValue(), batch.getPaymentTotalAmount());
364
365 message.setMessage(body.toString());
366
367 // KFSMI-6475 - if not a production instance, replace the recipients with the testers list
368 alterMessageWhenNonProductionInstance(message, null);
369
370 try {
371 mailService.sendMessage(message);
372 }
373 catch (InvalidAddressException e) {
374 LOG.error("sendErrorEmail() Invalid email address. Message not sent", e);
375 }
376 }
377
378 /**
379 * @see org.kuali.kfs.pdp.service.PdpEmailService#sendExceedsMaxNotesWarningEmail(java.util.List, java.util.List, int, int)
380 */
381 public void sendExceedsMaxNotesWarningEmail(List<String> creditMemos, List<String> paymentRequests, int lineTotal, int maxNoteLines) {
382 LOG.debug("sendExceedsMaxNotesWarningEmail() starting");
383
384 // check email configuration
385 if (!isPaymentEmailEnabled()) {
386 return;
387 }
388
389 MailMessage message = new MailMessage();
390 message.setFromAddress(mailService.getBatchMailingList());
391
392 StringBuffer body = new StringBuffer();
393
394 String environmentCode = kualiConfigurationService.getPropertyString(KFSConstants.ENVIRONMENT_KEY);
395 message.setSubject(getMessage(PdpKeyConstants.MESSAGE_PURAP_EXTRACT_MAX_NOTES_SUBJECT));
396
397 // Get recipient email address
398 String toAddresses = parameterService.getParameterValue(KfsParameterConstants.PRE_DISBURSEMENT_ALL.class, PdpParameterConstants.PDP_ERROR_EXCEEDS_NOTE_LIMIT_EMAIL);
399 List<String> toAddressList = Arrays.asList(toAddresses.split(","));
400 message.getToAddresses().addAll(toAddressList);
401
402 List<String> ccAddresses = parameterService.getParameterValues(LoadPaymentsStep.class, PdpParameterConstants.SOFT_EDIT_CC);
403 message.getCcAddresses().addAll(ccAddresses);
404
405
406 message.getBccAddresses().addAll(ccAddresses);
407
408 body.append(getMessage(PdpKeyConstants.MESSAGE_PURAP_EXTRACT_MAX_NOTES_MESSAGE, StringUtils.join(creditMemos, ","), StringUtils.join(paymentRequests, ","), lineTotal, maxNoteLines));
409 message.setMessage(body.toString());
410
411 // KFSMI-6475 - if not a production instance, replace the recipients with the testers list
412 alterMessageWhenNonProductionInstance(message, null);
413
414 try {
415 mailService.sendMessage(message);
416 }
417 catch (InvalidAddressException e) {
418 LOG.error("sendExceedsMaxNotesWarningEmail() Invalid email address. Message not sent", e);
419 }
420 }
421
422 /**
423 * @see org.kuali.kfs.pdp.service.PdpEmailService#sendAchSummaryEmail(java.util.Map, java.util.Map, java.util.Date)
424 */
425 public void sendAchSummaryEmail(Map<String, Integer> unitCounts, Map<String, KualiDecimal> unitTotals, Date disbursementDate) {
426 LOG.debug("sendAchSummaryEmail() starting");
427
428 MailMessage message = new MailMessage();
429
430 List<String> toAddressList = parameterService.getParameterValues(ExtractAchPaymentsStep.class, PdpParameterConstants.ACH_SUMMARY_TO_EMAIL_ADDRESS_PARMAETER_NAME);
431 message.getToAddresses().addAll(toAddressList);
432 message.getCcAddresses().addAll(toAddressList);
433 message.getBccAddresses().addAll(toAddressList);
434
435 message.setFromAddress(mailService.getBatchMailingList());
436
437 String subject = parameterService.getParameterValue(ExtractAchPaymentsStep.class, PdpParameterConstants.ACH_SUMMARY_EMAIL_SUBJECT_PARAMETER_NAME);
438 message.setSubject(subject);
439
440 StringBuffer body = new StringBuffer();
441 body.append(getMessage(PdpKeyConstants.MESSAGE_PDP_ACH_SUMMARY_EMAIL_DISB_DATE, disbursementDate) + "\n");
442
443 Integer totalCount = 0;
444 KualiDecimal totalAmount = KualiDecimal.ZERO;
445 for (String unit : unitCounts.keySet()) {
446 body.append(getMessage(PdpKeyConstants.MESSAGE_PDP_ACH_SUMMARY_EMAIL_UNIT_TOTAL, StringUtils.leftPad(unit, 13), StringUtils.leftPad(unitCounts.get(unit).toString(), 10), StringUtils.leftPad(unitTotals.get(unit).toString(), 20)) + "\n");
447
448 totalCount = totalCount + unitCounts.get(unit);
449 totalAmount = totalAmount.add(unitTotals.get(unit));
450 }
451
452 body.append(getMessage(PdpKeyConstants.MESSAGE_PDP_ACH_SUMMARY_EMAIL_EXTRACT_TOTALS, StringUtils.leftPad(totalCount.toString(), 10), StringUtils.leftPad(totalAmount.toString(), 20)) + "\n");
453 body.append(getMessage(PdpKeyConstants.MESSAGE_PDP_ACH_SUMMARY_EMAIL_COMPLETE));
454
455 message.setMessage(body.toString());
456
457 // KFSMI-6475 - if not a production instance, replace the recipients with the testers list
458 alterMessageWhenNonProductionInstance(message, null);
459
460 try {
461 mailService.sendMessage(message);
462 }
463 catch (InvalidAddressException e) {
464 LOG.error("sendAchSummaryEmail() Invalid email address. Message not sent", e);
465 }
466 }
467
468 /**
469 * @see org.kuali.kfs.pdp.service.PdpEmailService#sendAchAdviceEmail(org.kuali.kfs.pdp.businessobject.PaymentGroup,
470 * org.kuali.kfs.pdp.businessobject.CustomerProfile, org.kuali.kfs.pdp.businessobject.PaymentDetail)
471 */
472 public void sendAchAdviceEmail(PaymentGroup paymentGroup, PaymentDetail paymentDetail, CustomerProfile customer) {
473 LOG.debug("sendAchAdviceEmail() starting");
474
475 MailMessage message = new MailMessage();
476
477 message.addToAddress(paymentGroup.getAdviceEmailAddress());
478 message.addCcAddress(paymentGroup.getAdviceEmailAddress());
479 message.addBccAddress(paymentGroup.getAdviceEmailAddress());
480 message.setFromAddress(customer.getAdviceReturnEmailAddr());
481 message.setSubject(customer.getAdviceSubjectLine());
482
483 LOG.debug("sending email to " + paymentGroup.getAdviceEmailAddress() + " for disb # " + paymentGroup.getDisbursementNbr());
484
485 StringBuffer body = new StringBuffer();
486 body.append(getMessage(PdpKeyConstants.MESSAGE_PDP_ACH_ADVICE_EMAIL_TOFROM, paymentGroup.getPayeeName(), customer.getAchPaymentDescription()));
487
488 // formatter for payment amounts
489 Formatter formatter = new CurrencyFormatter();
490
491 // get bank name to which the payment is being transferred
492 String bankName = "";
493
494 ACHBank achBank = achBankService.getByPrimaryId(paymentGroup.getAchBankRoutingNbr());
495 if (achBank == null) {
496 LOG.error("Bank cound not be found for routing number " + paymentGroup.getAchBankRoutingNbr());
497 }
498 else {
499 bankName = achBank.getBankName();
500 }
501
502 body.append(getMessage(PdpKeyConstants.MESSAGE_PDP_ACH_ADVICE_EMAIL_BANKAMOUNT, bankName, formatter.formatForPresentation(paymentDetail.getNetPaymentAmount())));
503
504 // print detail amounts
505 int labelPad = 25;
506
507 String newPaymentAmountLabel = dataDictionaryService.getAttributeLabel(PaymentDetail.class, PdpPropertyConstants.PaymentDetail.PAYMENT_NET_AMOUNT);
508 body.append(StringUtils.rightPad(newPaymentAmountLabel, labelPad) + formatter.formatForPresentation(paymentDetail.getNetPaymentAmount()) + "\n");
509
510 if (paymentDetail.getOrigInvoiceAmount().isNonZero()) {
511 String origInvoiceAmountLabel = dataDictionaryService.getAttributeLabel(PaymentDetail.class, PdpPropertyConstants.PaymentDetail.PAYMENT_ORIGINAL_INVOICE_AMOUNT);
512 body.append(StringUtils.rightPad(origInvoiceAmountLabel, labelPad) + formatter.formatForPresentation(paymentDetail.getOrigInvoiceAmount()) + "\n");
513 }
514
515 if (paymentDetail.getInvTotDiscountAmount().isNonZero()) {
516 String invTotDiscountAmountLabel = dataDictionaryService.getAttributeLabel(PaymentDetail.class, PdpPropertyConstants.PaymentDetail.PAYMENT_INVOICE_TOTAL_DISCOUNT_AMOUNT);
517 body.append(StringUtils.rightPad(invTotDiscountAmountLabel, labelPad) + formatter.formatForPresentation(paymentDetail.getInvTotDiscountAmount()) + "\n");
518 }
519
520 if (paymentDetail.getInvTotShipAmount().isNonZero()) {
521 String invTotShippingAmountLabel = dataDictionaryService.getAttributeLabel(PaymentDetail.class, PdpPropertyConstants.PaymentDetail.PAYMENT_INVOICE_TOTAL_SHIPPING_AMOUNT);
522 body.append(StringUtils.rightPad(invTotShippingAmountLabel, labelPad) + formatter.formatForPresentation(paymentDetail.getInvTotShipAmount()) + "\n");
523 }
524
525 if (paymentDetail.getInvTotOtherDebitAmount().isNonZero()) {
526 String invTotOtherDebitAmountLabel = dataDictionaryService.getAttributeLabel(PaymentDetail.class, PdpPropertyConstants.PaymentDetail.PAYMENT_INVOICE_TOTAL_OTHER_DEBIT_AMOUNT);
527 body.append(StringUtils.rightPad(invTotOtherDebitAmountLabel, labelPad) + formatter.formatForPresentation(paymentDetail.getInvTotOtherDebitAmount()) + "\n");
528 }
529
530 if (paymentDetail.getInvTotOtherCreditAmount().isNonZero()) {
531 String invTotOtherCreditAmountLabel = dataDictionaryService.getAttributeLabel(PaymentDetail.class, PdpPropertyConstants.PaymentDetail.PAYMENT_INVOICE_TOTAL_OTHER_CREDIT_AMOUNT);
532 body.append(StringUtils.rightPad(invTotOtherCreditAmountLabel, labelPad) + formatter.formatForPresentation(paymentDetail.getInvTotOtherCreditAmount()) + "\n");
533 }
534
535 body.append("\n" + customer.getAdviceHeaderText() + "\n");
536
537 if (StringUtils.isNotBlank(paymentDetail.getPurchaseOrderNbr())) {
538 String purchaseOrderNbrLabel = dataDictionaryService.getAttributeLabel(PaymentDetail.class, PdpPropertyConstants.PaymentDetail.PAYMENT_PURCHASE_ORDER_NUMBER);
539 body.append(StringUtils.rightPad(purchaseOrderNbrLabel, labelPad) + paymentDetail.getPurchaseOrderNbr() + "\n");
540 }
541
542 if (StringUtils.isNotBlank(paymentDetail.getInvoiceNbr())) {
543 String invoiceNbrLabel = dataDictionaryService.getAttributeLabel(PaymentDetail.class, PdpPropertyConstants.PaymentDetail.PAYMENT_INVOICE_NUMBER);
544 body.append(StringUtils.rightPad(invoiceNbrLabel, labelPad) + paymentDetail.getInvoiceNbr() + "\n");
545 }
546
547 if (StringUtils.isNotBlank(paymentDetail.getCustPaymentDocNbr())) {
548 String custPaymentDocNbrLabel = dataDictionaryService.getAttributeLabel(PaymentDetail.class, PdpPropertyConstants.PaymentDetail.PAYMENT_CUSTOMER_DOC_NUMBER);
549 body.append(StringUtils.rightPad(custPaymentDocNbrLabel, labelPad) + paymentDetail.getCustPaymentDocNbr() + "\n");
550 }
551
552 if (StringUtils.isNotBlank(paymentGroup.getCustomerInstitutionNumber())) {
553 String customerInstituitionNbrLabel = dataDictionaryService.getAttributeLabel(PaymentGroup.class, PdpPropertyConstants.CUSTOMER_INSTITUTION_NUMBER);
554 body.append(StringUtils.rightPad(customerInstituitionNbrLabel, labelPad) + paymentGroup.getCustomerInstitutionNumber() + "\n");
555 }
556
557 body.append("\n");
558
559 // print payment notes
560 for (PaymentNoteText paymentNoteText : paymentDetail.getNotes()) {
561 body.append(paymentNoteText.getCustomerNoteText() + "\n");
562 }
563
564 if (paymentDetail.getNotes().isEmpty()) {
565 body.append(getMessage(PdpKeyConstants.MESSAGE_PDP_ACH_ADVICE_EMAIL_NONOTES));
566 }
567
568 message.setMessage(body.toString());
569
570 // KFSMI-6475 - if not a production instance, replace the recipients with the testers list
571 alterMessageWhenNonProductionInstance(message, null);
572
573 try {
574 mailService.sendMessage(message);
575 }
576 catch (InvalidAddressException e) {
577 LOG.error("sendAchAdviceEmail() Invalid email address. Sending message to " + customer.getAdviceReturnEmailAddr(), e);
578
579 // send notification to advice return address with payment details
580 message.addToAddress(customer.getAdviceReturnEmailAddr());
581
582 message.setFromAddress(mailService.getBatchMailingList());
583 message.setSubject(getMessage(PdpKeyConstants.MESSAGE_PDP_ACH_ADVICE_INVALID_EMAIL_ADDRESS));
584
585 LOG.debug("bouncing email to " + customer.getAdviceReturnEmailAddr() + " for disb # " + paymentGroup.getDisbursementNbr());
586 // KFSMI-6475 - if not a production instance, replace the recipients with the testers list
587 alterMessageWhenNonProductionInstance(message, null);
588
589 try {
590 mailService.sendMessage(message);
591 }
592 catch (InvalidAddressException e1) {
593 LOG.error("Could not send email to advice return email address on customer profile: " + customer.getAdviceReturnEmailAddr(), e1);
594 throw new RuntimeException("Could not send email to advice return email address on customer profile: " + customer.getAdviceReturnEmailAddr());
595 }
596 }
597 }
598
599 /**
600 *
601 * @see org.kuali.kfs.pdp.service.PdpEmailService#sendCancelEmail(org.kuali.kfs.pdp.businessobject.PaymentGroup, java.lang.String, org.kuali.rice.kim.bo.Person)
602 */
603 public void sendCancelEmail(PaymentGroup paymentGroup, String note, Person user) {
604 LOG.debug("sendCancelEmail() starting");
605
606 MailMessage message = new MailMessage();
607
608 String environmentCode = kualiConfigurationService.getPropertyString(KFSConstants.ENVIRONMENT_KEY);
609
610 message.setSubject("PDP --- Cancelled Payment by Tax");
611
612 CustomerProfile cp = paymentGroup.getBatch().getCustomerProfile();
613 String toAddresses = cp.getAdviceReturnEmailAddr();
614 String toAddressList[] = toAddresses.split(",");
615
616 if (toAddressList.length > 0) {
617 for (int i = 0; i < toAddressList.length; i++) {
618 if (toAddressList[i] != null) {
619 message.addToAddress(toAddressList[i].trim());
620 message.addBccAddress(toAddressList[i].trim());
621 }
622 }
623 }
624 // message.addToAddress(cp.getAdviceReturnEmailAddr());
625
626 String ccAddresses = parameterService.getParameterValue(KfsParameterConstants.PRE_DISBURSEMENT_ALL.class, PdpParameterConstants.TAX_CANCEL_EMAIL_LIST);
627 String ccAddressList[] = ccAddresses.split(",");
628
629 if (ccAddressList.length > 0) {
630 for (int i = 0; i < ccAddressList.length; i++) {
631 if (ccAddressList[i] != null) {
632 message.addCcAddress(ccAddressList[i].trim());
633 }
634 }
635 }
636
637 String fromAddressList[] = { mailService.getBatchMailingList() };
638
639 if (fromAddressList.length > 0) {
640 for (int i = 0; i < fromAddressList.length; i++) {
641 if (fromAddressList[i] != null) {
642 message.setFromAddress(fromAddressList[i].trim());
643 }
644 }
645 }
646
647 StringBuffer body = new StringBuffer();
648
649 String messageKey = kualiConfigurationService.getPropertyString(PdpKeyConstants.MESSAGE_PDP_PAYMENT_MAINTENANCE_EMAIL_LINE_1);
650 body.append(MessageFormat.format(messageKey, new Object[] { null }) + " \n\n");
651
652 body.append(note + "\n\n");
653 String taxEmail = parameterService.getParameterValue(KfsParameterConstants.PRE_DISBURSEMENT_ALL.class, PdpParameterConstants.TAX_GROUP_EMAIL_ADDRESS);
654 String taxContactDepartment = parameterService.getParameterValue(KfsParameterConstants.PRE_DISBURSEMENT_ALL.class, PdpParameterConstants.TAX_CANCEL_CONTACT);
655 if (StringUtils.isBlank(taxEmail)) {
656 messageKey = kualiConfigurationService.getPropertyString(PdpKeyConstants.MESSAGE_PDP_PAYMENT_MAINTENANCE_EMAIL_LINE_2);
657 body.append(MessageFormat.format(messageKey, new Object[] { taxContactDepartment }) + " \n\n");
658 }
659 else {
660 messageKey = kualiConfigurationService.getPropertyString(PdpKeyConstants.MESSAGE_PDP_PAYMENT_MAINTENANCE_EMAIL_LINE_3);
661 body.append(MessageFormat.format(messageKey, new Object[] { taxContactDepartment, taxEmail }) + " \n\n");
662 }
663
664 messageKey = kualiConfigurationService.getPropertyString(PdpKeyConstants.MESSAGE_PDP_PAYMENT_MAINTENANCE_EMAIL_LINE_4);
665 body.append(MessageFormat.format(messageKey, new Object[] { null }) + " \n\n");
666
667 for (PaymentDetail pd : paymentGroup.getPaymentDetails()) {
668
669 String payeeLabel = dataDictionaryService.getAttributeLabel(PaymentGroup.class, PdpPropertyConstants.PaymentGroup.PAYMENT_GROUP_PAYEE_NAME);
670 String netPaymentAccountLabel = dataDictionaryService.getAttributeLabel(PaymentDetail.class, PdpPropertyConstants.PaymentDetail.PAYMENT_NET_AMOUNT);
671 String sourceDocumentNumberLabel = dataDictionaryService.getAttributeLabel(PaymentDetail.class, PdpPropertyConstants.PaymentDetail.PAYMENT_DISBURSEMENT_CUST_PAYMENT_DOC_NBR);
672 String invoiceNumberLabel = dataDictionaryService.getAttributeLabel(PaymentDetail.class, PdpPropertyConstants.PaymentDetail.PAYMENT_INVOICE_NUMBER);
673 String purchaseOrderNumberLabel = dataDictionaryService.getAttributeLabel(PaymentDetail.class, PdpPropertyConstants.PaymentDetail.PAYMENT_PURCHASE_ORDER_NUMBER);
674 String paymentDetailIdLabel = dataDictionaryService.getAttributeLabel(PaymentDetail.class, PdpPropertyConstants.PaymentDetail.PAYMENT_ID);
675
676 body.append(payeeLabel + ": " + paymentGroup.getPayeeName() + " \n");
677 body.append(netPaymentAccountLabel + ": " + pd.getNetPaymentAmount() + " \n");
678 body.append(sourceDocumentNumberLabel + ": " + pd.getCustPaymentDocNbr() + " \n");
679 body.append(invoiceNumberLabel + ": " + pd.getInvoiceNbr() + " \n");
680 body.append(purchaseOrderNumberLabel + ": " + pd.getPurchaseOrderNbr() + " \n");
681 body.append(paymentDetailIdLabel + ": " + pd.getId() + "\n");
682
683 }
684
685 body.append(MessageFormat.format(messageKey, new Object[] { null }) + " \n\n");
686
687 String batchIdLabel = dataDictionaryService.getAttributeLabel(Batch.class, PdpPropertyConstants.BatchConstants.BATCH_ID);
688 String chartMessageLabel = dataDictionaryService.getAttributeLabel(CustomerProfile.class, PdpPropertyConstants.CustomerProfile.CUSTOMER_PROFILE_CHART_CODE);
689 String organizationLabel = dataDictionaryService.getAttributeLabel(CustomerProfile.class, PdpPropertyConstants.CustomerProfile.CUSTOMER_PROFILE_UNIT_CODE);
690 String subUnitLabel = dataDictionaryService.getAttributeLabel(CustomerProfile.class, PdpPropertyConstants.CustomerProfile.CUSTOMER_PROFILE_SUB_UNIT_CODE);
691 String creationDateLabel = dataDictionaryService.getAttributeLabel(Batch.class, PdpPropertyConstants.BatchConstants.FILE_CREATION_TIME);
692 String paymentCountLabel = dataDictionaryService.getAttributeLabel(Batch.class, PdpPropertyConstants.BatchConstants.PAYMENT_COUNT);
693 String paymentTotalLabel = dataDictionaryService.getAttributeLabel(Batch.class, PdpPropertyConstants.BatchConstants.PAYMENT_TOTAL_AMOUNT);
694
695 body.append(batchIdLabel + ": " + paymentGroup.getBatch().getId() + " \n");
696 body.append(chartMessageLabel + ": " + cp.getChartCode() + " \n");
697 body.append(organizationLabel + ": " + cp.getUnitCode() + " \n");
698 body.append(subUnitLabel + ": " + cp.getSubUnitCode() + " \n");
699 body.append(creationDateLabel + ": " + paymentGroup.getBatch().getCustomerFileCreateTimestamp() + " \n\n");
700 body.append(paymentCountLabel + ": " + paymentGroup.getBatch().getPaymentCount() + " \n\n");
701 body.append(paymentTotalLabel + ": " + paymentGroup.getBatch().getPaymentTotalAmount() + " \n\n");
702
703 message.setMessage(body.toString());
704
705 // KFSMI-6475 - if not a production instance, replace the recipients with the testers list
706 alterMessageWhenNonProductionInstance(message, null);
707
708 try {
709 mailService.sendMessage(message);
710 }
711 catch (InvalidAddressException e) {
712 LOG.error("sendErrorEmail() Invalid email address. Message not sent", e);
713 }
714 }
715
716 /**
717 * Writes out payment file field labels and values to <code>StringBuffer</code>
718 *
719 * @param body <code>StringBuffer</code>
720 */
721 protected void addPaymentFieldsToBody(StringBuffer body, Integer batchId, String chart, String unit, String subUnit, Date createDate, int paymentCount, KualiDecimal paymentTotal) {
722 String batchIdLabel = dataDictionaryService.getAttributeLabel(PaymentFileLoad.class, PdpPropertyConstants.BATCH_ID);
723 body.append(batchIdLabel + ": " + batchId + "\n");
724
725 String chartLabel = dataDictionaryService.getAttributeLabel(PaymentFileLoad.class, KFSPropertyConstants.CHART);
726 body.append(chartLabel + ": " + chart + "\n");
727
728 String orgLabel = dataDictionaryService.getAttributeLabel(PaymentFileLoad.class, PdpPropertyConstants.UNIT);
729 body.append(orgLabel + ": " + unit + "\n");
730
731 String subUnitLabel = dataDictionaryService.getAttributeLabel(PaymentFileLoad.class, PdpPropertyConstants.SUB_UNIT);
732 body.append(subUnitLabel + ": " + subUnit + "\n");
733
734 String createDateLabel = dataDictionaryService.getAttributeLabel(PaymentFileLoad.class, PdpPropertyConstants.CREATION_DATE);
735 body.append(createDateLabel + ": " + createDate + "\n");
736
737 String paymentCountLabel = dataDictionaryService.getAttributeLabel(PaymentFileLoad.class, PdpPropertyConstants.PAYMENT_COUNT);
738 body.append("\n" + paymentCountLabel + ": " + paymentCount + "\n");
739
740 String paymentTotalLabel = dataDictionaryService.getAttributeLabel(PaymentFileLoad.class, PdpPropertyConstants.PAYMENT_TOTAL_AMOUNT);
741 body.append(paymentTotalLabel + ": " + paymentTotal + "\n");
742 }
743
744 /**
745 * Reads system parameter indicating whether to status emails should be sent
746 *
747 * @return true if email should be sent, false otherwise
748 */
749 public boolean isPaymentEmailEnabled() {
750 boolean noEmail = parameterService.getIndicatorParameter(KfsParameterConstants.PRE_DISBURSEMENT_ALL.class, PdpParameterConstants.NO_PAYMENT_FILE_EMAIL);
751 if (noEmail) {
752 LOG.debug("sendLoadEmail() sending payment file email is disabled");
753 return false;
754 }
755
756 return true;
757 }
758
759 /**
760 * Retrieves the email subject text from system parameter then checks environment code and prepends to message if not
761 * production.
762 *
763 * @param subjectParmaterName name of parameter giving the subject text
764 * @return subject text
765 */
766 protected String getEmailSubject(String subjectParmaterName) {
767 String subject = parameterService.getParameterValue(LoadPaymentsStep.class, subjectParmaterName);
768
769 return subject;
770 }
771
772 /**
773 * Helper method to retrieve a message from resources and substitute place holder values
774 *
775 * @param messageKey key of message in resource file
776 * @param messageParameters parameter for message
777 * @return <code>String</code> Message with substituted values
778 */
779 protected String getMessage(String messageKey, Object... messageParameters) {
780 String message = kualiConfigurationService.getPropertyString(messageKey);
781 return MessageFormat.format(message, messageParameters);
782 }
783
784 /**
785 * Sets the customerProfileService attribute value.
786 *
787 * @param customerProfileService The customerProfileService to set.
788 */
789 public void setCustomerProfileService(CustomerProfileService customerProfileService) {
790 this.customerProfileService = customerProfileService;
791 }
792
793 /**
794 * Sets the kualiConfigurationService attribute value.
795 *
796 * @param kualiConfigurationService The kualiConfigurationService to set.
797 */
798 public void setKualiConfigurationService(KualiConfigurationService kualiConfigurationService) {
799 this.kualiConfigurationService = kualiConfigurationService;
800 }
801
802 /**
803 * Sets the mailService attribute value.
804 *
805 * @param mailService The mailService to set.
806 */
807 public void setMailService(MailService mailService) {
808 this.mailService = mailService;
809 }
810
811 /**
812 * Sets the parameterService attribute value.
813 *
814 * @param parameterService The parameterService to set.
815 */
816 public void setParameterService(ParameterService parameterService) {
817 this.parameterService = parameterService;
818 }
819
820 /**
821 * Sets the dataDictionaryService attribute value.
822 *
823 * @param dataDictionaryService The dataDictionaryService to set.
824 */
825 public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
826 this.dataDictionaryService = dataDictionaryService;
827 }
828
829 /**
830 * Sets the achBankService attribute value.
831 *
832 * @param achBankService The achBankService to set.
833 */
834 public void setAchBankService(AchBankService achBankService) {
835 this.achBankService = achBankService;
836 }
837
838 }