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 /*
017 * Created on Aug 12, 2004
018 */
019 package org.kuali.kfs.pdp.service.impl;
020
021 import java.sql.Timestamp;
022 import java.util.Date;
023 import java.util.HashMap;
024 import java.util.List;
025 import java.util.Map;
026
027 import org.kuali.kfs.pdp.PdpConstants;
028 import org.kuali.kfs.pdp.PdpKeyConstants;
029 import org.kuali.kfs.pdp.PdpPropertyConstants;
030 import org.kuali.kfs.pdp.businessobject.AchAccountNumber;
031 import org.kuali.kfs.pdp.businessobject.PaymentChangeCode;
032 import org.kuali.kfs.pdp.businessobject.PaymentDetail;
033 import org.kuali.kfs.pdp.businessobject.PaymentGroup;
034 import org.kuali.kfs.pdp.businessobject.PaymentGroupHistory;
035 import org.kuali.kfs.pdp.businessobject.PaymentNoteText;
036 import org.kuali.kfs.pdp.businessobject.PaymentStatus;
037 import org.kuali.kfs.pdp.dataaccess.PaymentDetailDao;
038 import org.kuali.kfs.pdp.dataaccess.PaymentGroupDao;
039 import org.kuali.kfs.pdp.service.EnvironmentService;
040 import org.kuali.kfs.pdp.service.PaymentGroupService;
041 import org.kuali.kfs.pdp.service.PaymentMaintenanceService;
042 import org.kuali.kfs.pdp.service.PdpAuthorizationService;
043 import org.kuali.kfs.pdp.service.PdpEmailService;
044 import org.kuali.kfs.pdp.service.PendingTransactionService;
045 import org.kuali.kfs.sys.KFSConstants;
046 import org.kuali.kfs.sys.service.BankService;
047 import org.kuali.rice.kim.bo.Person;
048 import org.kuali.rice.kns.bo.KualiCode;
049 import org.kuali.rice.kns.service.BusinessObjectService;
050 import org.kuali.rice.kns.service.MailService;
051 import org.kuali.rice.kns.service.ParameterService;
052 import org.kuali.rice.kns.util.GlobalVariables;
053 import org.kuali.rice.kns.util.KualiInteger;
054 import org.kuali.rice.kns.util.ObjectUtils;
055 import org.springframework.transaction.annotation.Transactional;
056
057 /**
058 * @see org.kuali.kfs.pdp.service.PaymentMaintenanceService
059 */
060 @Transactional
061 public class PaymentMaintenanceServiceImpl implements PaymentMaintenanceService {
062 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PaymentMaintenanceServiceImpl.class);
063
064 private PaymentGroupDao paymentGroupDao;
065 private PaymentDetailDao paymentDetailDao;
066 private PendingTransactionService glPendingTransactionService;
067 private EnvironmentService environmentService;
068 private MailService mailService;
069 private ParameterService parameterService;
070 private BankService bankService;
071 private BusinessObjectService businessObjectService;
072 private PaymentGroupService paymentGroupService;
073 private PdpEmailService emailService;
074 private PdpAuthorizationService pdpAuthorizationService;
075
076 /**
077 * This method changes status for a payment group.
078 *
079 * @param paymentGroup the payment group
080 * @param newPaymentStatus the new payment status
081 * @param changeStatus the changed payment status
082 * @param note a note for payment status change
083 * @param user the user that changed the status
084 */
085 protected void changeStatus(PaymentGroup paymentGroup, String newPaymentStatus, String changeStatus, String note, Person user) {
086 if (LOG.isDebugEnabled()) {
087 LOG.debug("changeStatus() enter method with new status of " + newPaymentStatus);
088 }
089
090 PaymentGroupHistory paymentGroupHistory = new PaymentGroupHistory();
091 KualiCode cd = businessObjectService.findBySinglePrimaryKey(PaymentChangeCode.class, changeStatus);
092 paymentGroupHistory.setPaymentChange((PaymentChangeCode) cd);
093 paymentGroupHistory.setOrigPaymentStatus(paymentGroup.getPaymentStatus());
094 paymentGroupHistory.setChangeUser(user);
095 paymentGroupHistory.setChangeNoteText(note);
096 paymentGroupHistory.setPaymentGroup(paymentGroup);
097 paymentGroupHistory.setChangeTime(new Timestamp(new Date().getTime()));
098
099 this.businessObjectService.save(paymentGroupHistory);
100
101 KualiCode code = businessObjectService.findBySinglePrimaryKey(PaymentStatus.class, newPaymentStatus);
102 paymentGroup.setPaymentStatus((PaymentStatus) code);
103 this.businessObjectService.save(paymentGroup);
104 LOG.debug("changeStatus() Status has been changed; exit method.");
105 }
106
107 /**
108 * This method changes the state of a paymentGroup.
109 *
110 * @param paymentGroup the payment group to change the state for
111 * @param newPaymentStatus the new payment status
112 * @param changeStatus the status that is changed
113 * @param note the note entered by the user
114 * @param user the user that changed the
115 * @param paymentGroupHistory
116 */
117 protected void changeStatus(PaymentGroup paymentGroup, String newPaymentStatus, String changeStatus, String note, Person user, PaymentGroupHistory paymentGroupHistory) {
118 if (LOG.isDebugEnabled()) {
119 LOG.debug("changeStatus() enter method with new status of " + newPaymentStatus);
120 }
121
122 KualiCode cd = businessObjectService.findBySinglePrimaryKey(PaymentChangeCode.class, changeStatus);
123 paymentGroupHistory.setPaymentChange((PaymentChangeCode) cd);
124 paymentGroupHistory.setOrigPaymentStatus(paymentGroup.getPaymentStatus());
125 paymentGroupHistory.setChangeUser(user);
126 paymentGroupHistory.setChangeNoteText(note);
127 paymentGroupHistory.setPaymentGroup(paymentGroup);
128 paymentGroupHistory.setChangeTime(new Timestamp(new Date().getTime()));
129
130 this.businessObjectService.save(paymentGroupHistory);
131
132 KualiCode code = businessObjectService.findBySinglePrimaryKey(PaymentStatus.class, newPaymentStatus);
133 if (paymentGroup.getPaymentStatus() != ((PaymentStatus) code)) {
134 paymentGroup.setPaymentStatus((PaymentStatus) code);
135 }
136 this.businessObjectService.save(paymentGroup);
137
138 LOG.debug("changeStatus() Status has been changed; exit method.");
139 }
140
141 /**
142 * @see org.kuali.kfs.pdp.document.service.PaymentMaintenanceService#cancelPendingPayment(java.lang.Integer, java.lang.Integer,
143 * java.lang.String, org.kuali.rice.kim.bo.Person)
144 */
145 public boolean cancelPendingPayment(Integer paymentGroupId, Integer paymentDetailId, String note, Person user) {
146 // All actions must be performed on entire group not individual detail record
147 if (LOG.isDebugEnabled()) {
148 LOG.debug("cancelPendingPayment() Enter method to cancel pending payment with group id = " + paymentGroupId);
149 LOG.debug("cancelPendingPayment() payment detail id being cancelled = " + paymentDetailId);
150 }
151
152 PaymentGroup paymentGroup = this.paymentGroupService.get(paymentGroupId);
153 if (paymentGroup == null) {
154 LOG.debug("cancelPendingPayment() Pending payment not found; throw exception.");
155 GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_PAYMENT_NOT_FOUND);
156 return false;
157 }
158
159 String paymentStatus = paymentGroup.getPaymentStatus().getCode();
160
161 if (!(PdpConstants.PaymentStatusCodes.CANCEL_PAYMENT.equals(paymentStatus))) {
162 if (LOG.isDebugEnabled()) {
163 LOG.debug("cancelPendingPayment() Payment status is " + paymentStatus + "; continue with cancel.");
164 }
165
166 if ((PdpConstants.PaymentStatusCodes.HELD_TAX_EMPLOYEE_CD.equals(paymentStatus)) || (PdpConstants.PaymentStatusCodes.HELD_TAX_NRA_CD.equals(paymentStatus)) || (PdpConstants.PaymentStatusCodes.HELD_TAX_NRA_EMPL_CD.equals(paymentStatus))) {
167 if (!pdpAuthorizationService.hasRemovePaymentTaxHoldPermission(user.getPrincipalId())) {
168 LOG.warn("cancelPendingPayment() Payment status is " + paymentStatus + "; user does not have rights to cancel. This should not happen unless user is URL spoofing.");
169 throw new RuntimeException("cancelPendingPayment() Payment status is " + paymentStatus + "; user does not have rights to cancel. This should not happen unless user is URL spoofing.");
170 }
171
172 changeStatus(paymentGroup, PdpConstants.PaymentStatusCodes.CANCEL_PAYMENT, PdpConstants.PaymentChangeCodes.CANCEL_PAYMENT_CHNG_CD, note, user);
173
174 // set primary cancel indicator for EPIC to use
175 Map primaryKeys = new HashMap();
176 primaryKeys.put(PdpPropertyConstants.PaymentDetail.PAYMENT_ID, paymentDetailId);
177
178 PaymentDetail pd = (PaymentDetail) this.businessObjectService.findByPrimaryKey(PaymentDetail.class, primaryKeys);
179 if (pd != null) {
180 pd.setPrimaryCancelledPayment(Boolean.TRUE);
181 }
182 this.businessObjectService.save(pd);
183 this.emailService.sendCancelEmail(paymentGroup, note, user);
184
185 LOG.debug("cancelPendingPayment() Pending payment cancelled and mail was sent; exit method.");
186 }
187 else if (PdpConstants.PaymentStatusCodes.OPEN.equals(paymentStatus) || PdpConstants.PaymentStatusCodes.HELD_CD.equals(paymentStatus)) {
188 if (!pdpAuthorizationService.hasCancelPaymentPermission(user.getPrincipalId())) {
189 LOG.warn("cancelPendingPayment() Payment status is " + paymentStatus + "; user does not have rights to cancel. This should not happen unless user is URL spoofing.");
190 throw new RuntimeException("cancelPendingPayment() Payment status is " + paymentStatus + "; user does not have rights to cancel. This should not happen unless user is URL spoofing.");
191 }
192
193 changeStatus(paymentGroup, PdpConstants.PaymentStatusCodes.CANCEL_PAYMENT, PdpConstants.PaymentChangeCodes.CANCEL_PAYMENT_CHNG_CD, note, user);
194
195 // set primary cancel indicator for EPIC to use
196 Map primaryKeys = new HashMap();
197 primaryKeys.put(PdpPropertyConstants.PaymentDetail.PAYMENT_ID, paymentDetailId);
198
199 PaymentDetail pd = (PaymentDetail) this.businessObjectService.findByPrimaryKey(PaymentDetail.class, primaryKeys);
200 if (pd != null) {
201 pd.setPrimaryCancelledPayment(Boolean.TRUE);
202 PaymentNoteText payNoteText = new PaymentNoteText();
203 payNoteText.setCustomerNoteLineNbr(new KualiInteger(pd.getNotes().size() + 1));
204 payNoteText.setCustomerNoteText(note);
205 pd.addNote(payNoteText);
206 }
207
208 this.businessObjectService.save(pd);
209
210 LOG.debug("cancelPendingPayment() Pending payment cancelled; exit method.");
211 }
212 else {
213 if (LOG.isDebugEnabled()) {
214 LOG.debug("cancelPendingPayment() Payment status is " + paymentStatus + "; cannot cancel payment in this status");
215 }
216
217 GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_PAYMENT_INVALID_STATUS_TO_CANCEL);
218 return false;
219 }
220 }
221 else {
222 LOG.debug("cancelPendingPayment() Pending payment group has already been cancelled; exit method.");
223 }
224 return true;
225 }
226
227 /**
228 * @see org.kuali.kfs.pdp.document.service.PaymentMaintenanceService#holdPendingPayment(java.lang.Integer, java.lang.String,
229 * org.kuali.rice.kim.bo.Person)
230 */
231 public boolean holdPendingPayment(Integer paymentGroupId, String note, Person user) {
232 // All actions must be performed on entire group not individual detail record
233 if (LOG.isDebugEnabled()) {
234 LOG.debug("holdPendingPayment() Enter method to hold pending payment with id = " + paymentGroupId);
235 }
236
237 if (!pdpAuthorizationService.hasHoldPaymentPermission(user.getPrincipalId())) {
238 LOG.warn("holdPendingPayment() User " + user.getPrincipalId() + " does not have rights to hold payments. This should not happen unless user is URL spoofing.");
239 throw new RuntimeException("holdPendingPayment() User " + user.getPrincipalId() + " does not have rights to hold payments. This should not happen unless user is URL spoofing.");
240 }
241
242 PaymentGroup paymentGroup = this.paymentGroupService.get(paymentGroupId);
243 if (paymentGroup == null) {
244 LOG.debug("holdPendingPayment() Pending payment not found; throw exception.");
245 GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_PAYMENT_NOT_FOUND);
246 return false;
247 }
248
249 String paymentStatus = paymentGroup.getPaymentStatus().getCode();
250
251 if (!(PdpConstants.PaymentStatusCodes.HELD_CD.equals(paymentStatus))) {
252 if (PdpConstants.PaymentStatusCodes.OPEN.equals(paymentStatus)) {
253 if (LOG.isDebugEnabled()) {
254 LOG.debug("holdPendingPayment() Payment status is " + paymentStatus + "; continue with hold.");
255 }
256
257 changeStatus(paymentGroup, PdpConstants.PaymentStatusCodes.HELD_CD, PdpConstants.PaymentChangeCodes.HOLD_CHNG_CD, note, user);
258
259 LOG.debug("holdPendingPayment() Pending payment was put on hold; exit method.");
260 }
261 else {
262 if (LOG.isDebugEnabled()) {
263 LOG.debug("holdPendingPayment() Payment status is " + paymentStatus + "; cannot hold payment in this status");
264 }
265
266 GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_PAYMENT_INVALID_STATUS_TO_HOLD);
267 return false;
268 }
269 }
270 else {
271 LOG.debug("holdPendingPayment() Pending payment group has already been held; exit method.");
272 }
273 return true;
274
275 }
276
277 /**
278 * @see org.kuali.kfs.pdp.document.service.PaymentMaintenanceService#removeHoldPendingPayment(java.lang.Integer,
279 * java.lang.String, org.kuali.rice.kim.bo.Person)
280 */
281 public boolean removeHoldPendingPayment(Integer paymentGroupId, String note, Person user) {
282 // All actions must be performed on entire group not individual detail record
283 if (LOG.isDebugEnabled()) {
284 LOG.debug("removeHoldPendingPayment() Enter method to hold pending payment with id = " + paymentGroupId);
285 }
286 PaymentGroup paymentGroup = this.paymentGroupService.get(paymentGroupId);
287 if (paymentGroup == null) {
288 LOG.debug("removeHoldPendingPayment() Payment not found; throw exception.");
289
290 GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_PAYMENT_NOT_FOUND);
291 return false;
292 }
293
294 String paymentStatus = paymentGroup.getPaymentStatus().getCode();
295
296 if (!(PdpConstants.PaymentStatusCodes.OPEN.equals(paymentStatus))) {
297 if (LOG.isDebugEnabled()) {
298 LOG.debug("removeHoldPendingPayment() Payment status is " + paymentStatus + "; continue with hold removal.");
299 }
300
301 if ((PdpConstants.PaymentStatusCodes.HELD_TAX_EMPLOYEE_CD.equals(paymentStatus)) || (PdpConstants.PaymentStatusCodes.HELD_TAX_NRA_CD.equals(paymentStatus)) || (PdpConstants.PaymentStatusCodes.HELD_TAX_NRA_EMPL_CD.equals(paymentStatus))) {
302 if (!pdpAuthorizationService.hasRemovePaymentTaxHoldPermission(user.getPrincipalId())) {
303 LOG.warn("removeHoldPendingPayment() User " + user.getPrincipalId() + " does not have rights to remove tax holds. This should not happen unless user is URL spoofing.");
304 throw new RuntimeException("removeHoldPendingPayment() User " + user.getPrincipalId() + " does not have rights to remove tax holds. This should not happen unless user is URL spoofing.");
305 }
306
307 changeStatus(paymentGroup, PdpConstants.PaymentStatusCodes.OPEN, PdpConstants.PaymentChangeCodes.REMOVE_HOLD_CHNG_CD, note, user);
308 LOG.debug("removeHoldPendingPayment() Pending payment was taken off hold; exit method.");
309 }
310 else if (PdpConstants.PaymentStatusCodes.HELD_CD.equals(paymentStatus)) {
311 if (!pdpAuthorizationService.hasHoldPaymentPermission(user.getPrincipalId())) {
312 LOG.warn("removeHoldPendingPayment() User " + user.getPrincipalId() + " does not have rights to hold payments. This should not happen unless user is URL spoofing.");
313 throw new RuntimeException("removeHoldPendingPayment() User " + user.getPrincipalId() + " does not have rights to hold payments. This should not happen unless user is URL spoofing.");
314 }
315
316 changeStatus(paymentGroup, PdpConstants.PaymentStatusCodes.OPEN, PdpConstants.PaymentChangeCodes.REMOVE_HOLD_CHNG_CD, note, user);
317
318 LOG.debug("removeHoldPendingPayment() Pending payment was taken off hold; exit method.");
319 }
320 else {
321 if (LOG.isDebugEnabled()) {
322 LOG.debug("removeHoldPendingPayment() Payment status is " + paymentStatus + "; cannot remove hold on payment in this status");
323 }
324
325 GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_PAYMENT_INVALID_STATUS_TO_REMOVE_HOLD);
326 return false;
327 }
328 }
329 else {
330 LOG.debug("removeHoldPendingPayment() Pending payment group has already been un-held; exit method.");
331 }
332 return true;
333 }
334
335 /**
336 * @see org.kuali.kfs.pdp.document.service.PaymentMaintenanceService#changeImmediateFlag(java.lang.Integer, java.lang.String,
337 * org.kuali.rice.kim.bo.Person)
338 */
339 public void changeImmediateFlag(Integer paymentGroupId, String note, Person user) {
340 // All actions must be performed on entire group not individual detail record
341 if (LOG.isDebugEnabled()) {
342 LOG.debug("changeImmediateFlag() Enter method to hold pending payment with id = " + paymentGroupId);
343 }
344
345 if (!pdpAuthorizationService.hasSetAsImmediatePayPermission(user.getPrincipalId())) {
346 LOG.warn("changeImmediateFlag() User " + user.getPrincipalId() + " does not have rights to set payments as immediate. This should not happen unless user is URL spoofing.");
347 throw new RuntimeException("changeImmediateFlag() User " + user.getPrincipalId() + " does not have rights to payments as immediate. This should not happen unless user is URL spoofing.");
348 }
349
350 PaymentGroupHistory paymentGroupHistory = new PaymentGroupHistory();
351 PaymentGroup paymentGroup = this.paymentGroupService.get(paymentGroupId);
352
353 paymentGroupHistory.setOrigProcessImmediate(paymentGroup.getProcessImmediate());
354
355 if (paymentGroup.getProcessImmediate().equals(Boolean.TRUE)) {
356 paymentGroup.setProcessImmediate(Boolean.FALSE);
357 }
358 else {
359 paymentGroup.setProcessImmediate(Boolean.TRUE);
360 }
361
362 changeStatus(paymentGroup, paymentGroup.getPaymentStatus().getCode(), PdpConstants.PaymentChangeCodes.CHANGE_IMMEDIATE_CHNG_CD, note, user, paymentGroupHistory);
363
364 LOG.debug("changeImmediateFlag() exit method.");
365 }
366
367 /**
368 * @see org.kuali.kfs.pdp.document.service.PaymentMaintenanceService#cancelDisbursement(java.lang.Integer, java.lang.Integer,
369 * java.lang.String, org.kuali.rice.kim.bo.Person)
370 */
371 public boolean cancelDisbursement(Integer paymentGroupId, Integer paymentDetailId, String note, Person user) {
372 // All actions must be performed on entire group not individual detail record
373 if (LOG.isDebugEnabled()) {
374 LOG.debug("cancelDisbursement() Enter method to cancel disbursement with id = " + paymentGroupId);
375 }
376
377 if (!pdpAuthorizationService.hasCancelPaymentPermission(user.getPrincipalId())) {
378 LOG.warn("cancelDisbursement() User " + user.getPrincipalId() + " does not have rights to cancel payments. This should not happen unless user is URL spoofing.");
379 throw new RuntimeException("cancelDisbursement() User " + user.getPrincipalId() + " does not have rights to cancel payments. This should not happen unless user is URL spoofing.");
380 }
381
382 PaymentGroup paymentGroup = this.paymentGroupService.get(paymentGroupId);
383
384 if (paymentGroup == null) {
385 LOG.debug("cancelDisbursement() Disbursement not found; throw exception.");
386 GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_DISBURSEMENT_NOT_FOUND);
387 return false;
388 }
389
390 String paymentStatus = paymentGroup.getPaymentStatus().getCode();
391
392 if (!(PdpConstants.PaymentStatusCodes.CANCEL_DISBURSEMENT.equals(paymentStatus))) {
393 if (((PdpConstants.PaymentStatusCodes.EXTRACTED.equals(paymentStatus)) && (ObjectUtils.isNotNull(paymentGroup.getDisbursementDate()))) || (PdpConstants.PaymentStatusCodes.PENDING_ACH.equals(paymentStatus))) {
394 if (LOG.isDebugEnabled()) {
395 LOG.debug("cancelDisbursement() Payment status is " + paymentStatus + "; continue with cancel.");
396 }
397
398 List<PaymentGroup> allDisbursementPaymentGroups = this.paymentGroupService.getByDisbursementNumber(paymentGroup.getDisbursementNbr().intValue());
399
400 for (PaymentGroup element : allDisbursementPaymentGroups) {
401 PaymentGroupHistory pgh = new PaymentGroupHistory();
402
403 if (!element.getPaymentDetails().get(0).isDisbursementActionAllowed()) {
404 LOG.warn("cancelDisbursement() Payment does not allow disbursement action. This should not happen unless user is URL spoofing.");
405 throw new RuntimeException("cancelDisbursement() Payment does not allow disbursement action. This should not happen unless user is URL spoofing.");
406 }
407
408 if ((ObjectUtils.isNotNull(element.getDisbursementType())) && (element.getDisbursementType().getCode().equals(PdpConstants.DisbursementTypeCodes.CHECK))) {
409 pgh.setPmtCancelExtractStat(Boolean.FALSE);
410 }
411
412 changeStatus(element, PdpConstants.PaymentStatusCodes.CANCEL_DISBURSEMENT, PdpConstants.PaymentChangeCodes.CANCEL_DISBURSEMENT, note, user, pgh);
413
414 glPendingTransactionService.generateCancellationGeneralLedgerPendingEntry(element);
415 }
416
417 // set primary cancel indicator for EPIC to use
418 Map primaryKeys = new HashMap();
419 primaryKeys.put(PdpPropertyConstants.PaymentDetail.PAYMENT_ID, paymentDetailId);
420
421 PaymentDetail pd = (PaymentDetail) this.businessObjectService.findByPrimaryKey(PaymentDetail.class, primaryKeys);
422 if (pd != null) {
423 pd.setPrimaryCancelledPayment(Boolean.TRUE);
424 }
425
426 this.businessObjectService.save(pd);
427
428 LOG.debug("cancelDisbursement() Disbursement cancelled; exit method.");
429 }
430 else {
431 if (LOG.isDebugEnabled()) {
432 LOG.debug("cancelDisbursement() Payment status is " + paymentStatus + " and disbursement date is " + paymentGroup.getDisbursementDate() + "; cannot cancel payment in this status");
433 }
434
435 GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_DISBURSEMENT_INVALID_TO_CANCEL);
436 return false;
437 }
438 }
439 else {
440 LOG.debug("cancelDisbursement() Disbursement has already been cancelled; exit method.");
441 }
442 return true;
443 }
444
445 /**
446 * @see org.kuali.kfs.pdp.document.service.PaymentMaintenanceService#cancelReissueDisbursement(java.lang.Integer,
447 * java.lang.String, org.kuali.rice.kim.bo.Person)
448 */
449 public boolean cancelReissueDisbursement(Integer paymentGroupId, String note, Person user) {
450 // All actions must be performed on entire group not individual detail record
451 if (LOG.isDebugEnabled()) {
452 LOG.debug("cancelReissueDisbursement() Enter method to cancel disbursement with id = " + paymentGroupId);
453 }
454
455 if (!pdpAuthorizationService.hasCancelPaymentPermission(user.getPrincipalId())) {
456 LOG.warn("cancelReissueDisbursement() User " + user.getPrincipalId() + " does not have rights to cancel payments. This should not happen unless user is URL spoofing.");
457 throw new RuntimeException("cancelReissueDisbursement() User " + user.getPrincipalId() + " does not have rights to cancel payments. This should not happen unless user is URL spoofing.");
458 }
459
460 PaymentGroup paymentGroup = this.paymentGroupService.get(paymentGroupId);
461 if (paymentGroup == null) {
462 LOG.debug("cancelReissueDisbursement() Disbursement not found; throw exception.");
463 GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_DISBURSEMENT_NOT_FOUND);
464 return false;
465 }
466
467 String paymentStatus = paymentGroup.getPaymentStatus().getCode();
468
469 if (!(PdpConstants.PaymentStatusCodes.OPEN.equals(paymentStatus))) {
470 if (((PdpConstants.PaymentStatusCodes.EXTRACTED.equals(paymentStatus)) && (ObjectUtils.isNotNull(paymentGroup.getDisbursementDate()))) || (PdpConstants.PaymentStatusCodes.PENDING_ACH.equals(paymentStatus))) {
471 if (LOG.isDebugEnabled()) {
472 LOG.debug("cancelReissueDisbursement() Payment status is " + paymentStatus + "; continue with cancel.");
473 }
474
475 List<PaymentGroup> allDisbursementPaymentGroups = this.paymentGroupService.getByDisbursementNumber(paymentGroup.getDisbursementNbr().intValue());
476
477 for (PaymentGroup pg : allDisbursementPaymentGroups) {
478 PaymentGroupHistory pgh = new PaymentGroupHistory();
479
480 if (!pg.getPaymentDetails().get(0).isDisbursementActionAllowed()) {
481 LOG.warn("cancelDisbursement() Payment does not allow disbursement action. This should not happen unless user is URL spoofing.");
482 throw new RuntimeException("cancelDisbursement() Payment does not allow disbursement action. This should not happen unless user is URL spoofing.");
483 }
484
485 if ((ObjectUtils.isNotNull(pg.getDisbursementType())) && (pg.getDisbursementType().getCode().equals(PdpConstants.DisbursementTypeCodes.CHECK))) {
486 pgh.setPmtCancelExtractStat(Boolean.FALSE);
487 }
488
489 pgh.setOrigProcessImmediate(pg.getProcessImmediate());
490 pgh.setOrigPmtSpecHandling(pg.getPymtSpecialHandling());
491 pgh.setBank(pg.getBank());
492 pgh.setOrigPaymentDate(pg.getPaymentDate());
493 //put a check for null since disbursement date was not set in testMode / dev
494 if (ObjectUtils.isNotNull(pg.getDisbursementDate())) {
495 pgh.setOrigDisburseDate(new Timestamp(pg.getDisbursementDate().getTime()));
496 }
497 pgh.setOrigAchBankRouteNbr(pg.getAchBankRoutingNbr());
498 pgh.setOrigDisburseNbr(pg.getDisbursementNbr());
499 pgh.setOrigAdviceEmail(pg.getAdviceEmailAddress());
500 pgh.setDisbursementType(pg.getDisbursementType());
501 pgh.setProcess(pg.getProcess());
502
503 glPendingTransactionService.generateReissueGeneralLedgerPendingEntry(pg);
504
505 if (LOG.isDebugEnabled()) {
506 LOG.debug("cancelReissueDisbursement() Status is '" + paymentStatus + "; delete row from AchAccountNumber table.");
507 }
508
509 AchAccountNumber achAccountNumber = pg.getAchAccountNumber();
510
511 if (ObjectUtils.isNotNull(achAccountNumber)) {
512 this.businessObjectService.delete(achAccountNumber);
513 pg.setAchAccountNumber(null);
514 }
515
516 // if bank functionality is not enabled or the group bank is inactive clear bank code
517 if (!bankService.isBankSpecificationEnabled() || !pg.getBank().isActive()) {
518 pg.setBank(null);
519 }
520
521 pg.setDisbursementDate((java.sql.Date) null);
522 pg.setAchBankRoutingNbr(null);
523 pg.setAchAccountType(null);
524 pg.setPhysCampusProcessCd(null);
525 pg.setDisbursementNbr((KualiInteger) null);
526 pg.setAdviceEmailAddress(null);
527 pg.setDisbursementType(null);
528 pg.setProcess(null);
529 pg.setProcessImmediate(false);
530
531 changeStatus(pg, PdpConstants.PaymentStatusCodes.OPEN, PdpConstants.PaymentChangeCodes.CANCEL_REISSUE_DISBURSEMENT, note, user, pgh);
532 }
533
534 LOG.debug("cancelReissueDisbursement() Disbursement cancelled and reissued; exit method.");
535 }
536 else {
537 if (LOG.isDebugEnabled()) {
538 LOG.debug("cancelReissueDisbursement() Payment status is " + paymentStatus + " and disbursement date is " + paymentGroup.getDisbursementDate() + "; cannot cancel payment");
539 }
540
541 GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_DISBURSEMENT_INVALID_TO_CANCEL_AND_REISSUE);
542 return false;
543 }
544 }
545 else {
546 LOG.debug("cancelReissueDisbursement() Disbursement already cancelled and reissued; exit method.");
547 }
548 return true;
549 }
550
551 /**
552 * inject
553 *
554 * @param dao
555 */
556 public void setPaymentGroupDao(PaymentGroupDao dao) {
557 paymentGroupDao = dao;
558 }
559
560 /**
561 * inject
562 *
563 * @param dao
564 */
565 public void setPaymentDetailDao(PaymentDetailDao dao) {
566 paymentDetailDao = dao;
567 }
568
569 /**
570 * inject
571 *
572 * @param service
573 */
574 public void setGlPendingTransactionService(PendingTransactionService service) {
575 glPendingTransactionService = service;
576 }
577
578 /**
579 * inject
580 *
581 * @param service
582 */
583 public void setEnvironmentService(EnvironmentService environmentService) {
584 this.environmentService = environmentService;
585 }
586
587 /**
588 * inject
589 *
590 * @param service
591 */
592 public void setMailService(MailService mailService) {
593 this.mailService = mailService;
594 }
595
596 public void setParameterService(ParameterService parameterService) {
597 this.parameterService = parameterService;
598 }
599
600 /**
601 * Sets the bankService attribute value.
602 *
603 * @param bankService The bankService to set.
604 */
605 public void setBankService(BankService bankService) {
606 this.bankService = bankService;
607 }
608
609 /**
610 * Sets the business object service
611 *
612 * @param businessObjectService
613 */
614 public void setBusinessObjectService(BusinessObjectService businessObjectService) {
615 this.businessObjectService = businessObjectService;
616 }
617
618 /**
619 * Sets the payment group service
620 *
621 * @param paymentGroupService
622 */
623 public void setPaymentGroupService(PaymentGroupService paymentGroupService) {
624 this.paymentGroupService = paymentGroupService;
625 }
626
627 public void setEmailService(PdpEmailService emailService) {
628 this.emailService = emailService;
629 }
630
631 public void setPdpAuthorizationService(PdpAuthorizationService pdpAuthorizationService) {
632 this.pdpAuthorizationService = pdpAuthorizationService;
633 }
634 }