View Javadoc
1   /*
2    * Copyright 2007 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  /*
17   * Created on Aug 12, 2004
18   */
19  package org.kuali.ole.pdp.service.impl;
20  
21  import java.sql.Timestamp;
22  import java.util.Date;
23  import java.util.HashMap;
24  import java.util.List;
25  import java.util.Map;
26  
27  import org.kuali.ole.pdp.PdpConstants;
28  import org.kuali.ole.pdp.PdpKeyConstants;
29  import org.kuali.ole.pdp.PdpPropertyConstants;
30  import org.kuali.ole.pdp.businessobject.AchAccountNumber;
31  import org.kuali.ole.pdp.businessobject.PaymentChangeCode;
32  import org.kuali.ole.pdp.businessobject.PaymentDetail;
33  import org.kuali.ole.pdp.businessobject.PaymentGroup;
34  import org.kuali.ole.pdp.businessobject.PaymentGroupHistory;
35  import org.kuali.ole.pdp.businessobject.PaymentNoteText;
36  import org.kuali.ole.pdp.businessobject.PaymentStatus;
37  import org.kuali.ole.pdp.dataaccess.PaymentDetailDao;
38  import org.kuali.ole.pdp.dataaccess.PaymentGroupDao;
39  import org.kuali.ole.pdp.service.PaymentGroupService;
40  import org.kuali.ole.pdp.service.PaymentMaintenanceService;
41  import org.kuali.ole.pdp.service.PdpAuthorizationService;
42  import org.kuali.ole.pdp.service.PdpEmailService;
43  import org.kuali.ole.pdp.service.PendingTransactionService;
44  import org.kuali.ole.sys.OLEConstants;
45  import org.kuali.ole.sys.service.BankService;
46  import org.kuali.rice.core.api.util.type.KualiInteger;
47  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
48  import org.kuali.rice.kim.api.identity.Person;
49  import org.kuali.rice.krad.bo.KualiCode;
50  import org.kuali.rice.krad.service.BusinessObjectService;
51  import org.kuali.rice.krad.service.MailService;
52  import org.kuali.rice.krad.util.GlobalVariables;
53  import org.kuali.rice.krad.util.ObjectUtils;
54  import org.springframework.transaction.annotation.Transactional;
55  
56  /**
57   * @see org.kuali.ole.pdp.service.PaymentMaintenanceService
58   */
59  @Transactional
60  public class PaymentMaintenanceServiceImpl implements PaymentMaintenanceService {
61      private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PaymentMaintenanceServiceImpl.class);
62  
63      private PaymentGroupDao paymentGroupDao;
64      private PaymentDetailDao paymentDetailDao;
65      private PendingTransactionService glPendingTransactionService;
66      private MailService mailService;
67      private ParameterService parameterService;
68      private BankService bankService;
69      private BusinessObjectService businessObjectService;
70      private PaymentGroupService paymentGroupService;
71      private PdpEmailService emailService;
72      private PdpAuthorizationService pdpAuthorizationService;
73  
74      /**
75       * This method changes status for a payment group.
76       *
77       * @param paymentGroup the payment group
78       * @param newPaymentStatus the new payment status
79       * @param changeStatus the changed payment status
80       * @param note a note for payment status change
81       * @param user the user that changed the status
82       */
83      protected void changeStatus(PaymentGroup paymentGroup, String newPaymentStatus, String changeStatus, String note, Person user) {
84          if (LOG.isDebugEnabled()) {
85              LOG.debug("changeStatus() enter method with new status of " + newPaymentStatus);
86          }
87  
88          PaymentGroupHistory paymentGroupHistory = new PaymentGroupHistory();
89          KualiCode cd = businessObjectService.findBySinglePrimaryKey(PaymentChangeCode.class, changeStatus);
90          paymentGroupHistory.setPaymentChange((PaymentChangeCode) cd);
91          paymentGroupHistory.setOrigPaymentStatus(paymentGroup.getPaymentStatus());
92          paymentGroupHistory.setChangeUser(user);
93          paymentGroupHistory.setChangeNoteText(note);
94          paymentGroupHistory.setPaymentGroup(paymentGroup);
95          paymentGroupHistory.setChangeTime(new Timestamp(new Date().getTime()));
96  
97          this.businessObjectService.save(paymentGroupHistory);
98  
99          KualiCode code = businessObjectService.findBySinglePrimaryKey(PaymentStatus.class, newPaymentStatus);
100         paymentGroup.setPaymentStatus((PaymentStatus) code);
101         this.businessObjectService.save(paymentGroup);
102         LOG.debug("changeStatus() Status has been changed; exit method.");
103     }
104 
105     /**
106      * This method changes the state of a paymentGroup.
107      *
108      * @param paymentGroup the payment group to change the state for
109      * @param newPaymentStatus the new payment status
110      * @param changeStatus the status that is changed
111      * @param note the note entered by the user
112      * @param user the user that changed the
113      * @param paymentGroupHistory
114      */
115     protected void changeStatus(PaymentGroup paymentGroup, String newPaymentStatus, String changeStatus, String note, Person user, PaymentGroupHistory paymentGroupHistory) {
116         if (LOG.isDebugEnabled()) {
117             LOG.debug("changeStatus() enter method with new status of " + newPaymentStatus);
118         }
119 
120         KualiCode cd = businessObjectService.findBySinglePrimaryKey(PaymentChangeCode.class, changeStatus);
121         paymentGroupHistory.setPaymentChange((PaymentChangeCode) cd);
122         paymentGroupHistory.setOrigPaymentStatus(paymentGroup.getPaymentStatus());
123         paymentGroupHistory.setChangeUser(user);
124         paymentGroupHistory.setChangeNoteText(note);
125         paymentGroupHistory.setPaymentGroup(paymentGroup);
126         paymentGroupHistory.setChangeTime(new Timestamp(new Date().getTime()));
127 
128         this.businessObjectService.save(paymentGroupHistory);
129 
130         KualiCode code = businessObjectService.findBySinglePrimaryKey(PaymentStatus.class, newPaymentStatus);
131         if (paymentGroup.getPaymentStatus() != ((PaymentStatus) code)) {
132             paymentGroup.setPaymentStatus((PaymentStatus) code);
133         }
134         this.businessObjectService.save(paymentGroup);
135 
136         LOG.debug("changeStatus() Status has been changed; exit method.");
137     }
138 
139     /**
140      * @see org.kuali.ole.pdp.document.service.PaymentMaintenanceService#cancelPendingPayment(java.lang.Integer, java.lang.Integer,
141      *      java.lang.String, org.kuali.rice.kim.api.identity.Person)
142      */
143     @Override
144     public boolean cancelPendingPayment(Integer paymentGroupId, Integer paymentDetailId, String note, Person user) {
145         // All actions must be performed on entire group not individual detail record
146         if (LOG.isDebugEnabled()) {
147             LOG.debug("cancelPendingPayment() Enter method to cancel pending payment with group id = " + paymentGroupId);
148             LOG.debug("cancelPendingPayment() payment detail id being cancelled = " + paymentDetailId);
149         }
150 
151         PaymentGroup paymentGroup = this.paymentGroupService.get(paymentGroupId);
152         if (paymentGroup == null) {
153             LOG.debug("cancelPendingPayment() Pending payment not found; throw exception.");
154             GlobalVariables.getMessageMap().putError(OLEConstants.GLOBAL_ERRORS, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_PAYMENT_NOT_FOUND);
155             return false;
156         }
157 
158         String paymentStatus = paymentGroup.getPaymentStatus().getCode();
159 
160         if (!(PdpConstants.PaymentStatusCodes.CANCEL_PAYMENT.equals(paymentStatus))) {
161             if (LOG.isDebugEnabled()) {
162                 LOG.debug("cancelPendingPayment() Payment status is " + paymentStatus + "; continue with cancel.");
163             }
164 
165             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))) {
166                 if (!pdpAuthorizationService.hasRemovePaymentTaxHoldPermission(user.getPrincipalId())) {
167                     LOG.warn("cancelPendingPayment() Payment status is " + paymentStatus + "; user does not have rights to cancel. This should not happen unless user is URL spoofing.");
168                     throw new RuntimeException("cancelPendingPayment() Payment status is " + paymentStatus + "; user does not have rights to cancel. This should not happen unless user is URL spoofing.");
169                 }
170 
171                 changeStatus(paymentGroup, PdpConstants.PaymentStatusCodes.CANCEL_PAYMENT, PdpConstants.PaymentChangeCodes.CANCEL_PAYMENT_CHNG_CD, note, user);
172 
173                 // set primary cancel indicator for EPIC to use
174                 Map primaryKeys = new HashMap();
175                 primaryKeys.put(PdpPropertyConstants.PaymentDetail.PAYMENT_ID, paymentDetailId);
176 
177                 PaymentDetail pd = (PaymentDetail) this.businessObjectService.findByPrimaryKey(PaymentDetail.class, primaryKeys);
178                 if (pd != null) {
179                     pd.setPrimaryCancelledPayment(Boolean.TRUE);
180                 }
181                 this.businessObjectService.save(pd);
182                 this.emailService.sendCancelEmail(paymentGroup, note, user);
183 
184                 LOG.debug("cancelPendingPayment() Pending payment cancelled and mail was sent; exit method.");
185             }
186             else if (PdpConstants.PaymentStatusCodes.OPEN.equals(paymentStatus) || PdpConstants.PaymentStatusCodes.HELD_CD.equals(paymentStatus)) {
187                 if (!pdpAuthorizationService.hasCancelPaymentPermission(user.getPrincipalId())) {
188                     LOG.warn("cancelPendingPayment() Payment status is " + paymentStatus + "; user does not have rights to cancel. This should not happen unless user is URL spoofing.");
189                     throw new RuntimeException("cancelPendingPayment() Payment status is " + paymentStatus + "; user does not have rights to cancel. This should not happen unless user is URL spoofing.");
190                 }
191 
192                 changeStatus(paymentGroup, PdpConstants.PaymentStatusCodes.CANCEL_PAYMENT, PdpConstants.PaymentChangeCodes.CANCEL_PAYMENT_CHNG_CD, note, user);
193 
194                 // set primary cancel indicator for EPIC to use
195                 Map primaryKeys = new HashMap();
196                 primaryKeys.put(PdpPropertyConstants.PaymentDetail.PAYMENT_ID, paymentDetailId);
197 
198                 PaymentDetail pd = (PaymentDetail) this.businessObjectService.findByPrimaryKey(PaymentDetail.class, primaryKeys);
199                 if (pd != null) {
200                     pd.setPrimaryCancelledPayment(Boolean.TRUE);
201                     PaymentNoteText payNoteText = new PaymentNoteText();
202                     payNoteText.setCustomerNoteLineNbr(new KualiInteger(pd.getNotes().size() + 1));
203                     payNoteText.setCustomerNoteText(note);
204                     pd.addNote(payNoteText);
205                 }
206 
207                 this.businessObjectService.save(pd);
208 
209                 LOG.debug("cancelPendingPayment() Pending payment cancelled; exit method.");
210             }
211             else {
212                 if (LOG.isDebugEnabled()) {
213                     LOG.debug("cancelPendingPayment() Payment status is " + paymentStatus + "; cannot cancel payment in this status");
214                 }
215 
216                 GlobalVariables.getMessageMap().putError(OLEConstants.GLOBAL_ERRORS, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_PAYMENT_INVALID_STATUS_TO_CANCEL);
217                 return false;
218             }
219         }
220         else {
221             LOG.debug("cancelPendingPayment() Pending payment group has already been cancelled; exit method.");
222         }
223         return true;
224     }
225 
226     /**
227      * @see org.kuali.ole.pdp.document.service.PaymentMaintenanceService#holdPendingPayment(java.lang.Integer, java.lang.String,
228      *      org.kuali.rice.kim.api.identity.Person)
229      */
230     @Override
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(OLEConstants.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(OLEConstants.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.ole.pdp.document.service.PaymentMaintenanceService#removeHoldPendingPayment(java.lang.Integer,
279      *      java.lang.String, org.kuali.rice.kim.api.identity.Person)
280      */
281     @Override
282     public boolean removeHoldPendingPayment(Integer paymentGroupId, String note, Person user) {
283         // All actions must be performed on entire group not individual detail record
284         if (LOG.isDebugEnabled()) {
285             LOG.debug("removeHoldPendingPayment() Enter method to hold pending payment with id = " + paymentGroupId);
286         }
287         PaymentGroup paymentGroup = this.paymentGroupService.get(paymentGroupId);
288         if (paymentGroup == null) {
289             LOG.debug("removeHoldPendingPayment() Payment not found; throw exception.");
290 
291             GlobalVariables.getMessageMap().putError(OLEConstants.GLOBAL_ERRORS, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_PAYMENT_NOT_FOUND);
292             return false;
293         }
294 
295         String paymentStatus = paymentGroup.getPaymentStatus().getCode();
296 
297         if (!(PdpConstants.PaymentStatusCodes.OPEN.equals(paymentStatus))) {
298             if (LOG.isDebugEnabled()) {
299                 LOG.debug("removeHoldPendingPayment() Payment status is " + paymentStatus + "; continue with hold removal.");
300             }
301 
302             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))) {
303                 if (!pdpAuthorizationService.hasRemovePaymentTaxHoldPermission(user.getPrincipalId())) {
304                     LOG.warn("removeHoldPendingPayment() User " + user.getPrincipalId() + " does not have rights to remove tax holds. This should not happen unless user is URL spoofing.");
305                     throw new RuntimeException("removeHoldPendingPayment() User " + user.getPrincipalId() + " does not have rights to remove tax holds. This should not happen unless user is URL spoofing.");
306                 }
307 
308                 changeStatus(paymentGroup, PdpConstants.PaymentStatusCodes.OPEN, PdpConstants.PaymentChangeCodes.REMOVE_HOLD_CHNG_CD, note, user);
309                 LOG.debug("removeHoldPendingPayment() Pending payment was taken off hold; exit method.");
310             }
311             else if (PdpConstants.PaymentStatusCodes.HELD_CD.equals(paymentStatus)) {
312                 if (!pdpAuthorizationService.hasHoldPaymentPermission(user.getPrincipalId())) {
313                     LOG.warn("removeHoldPendingPayment() User " + user.getPrincipalId() + " does not have rights to hold payments. This should not happen unless user is URL spoofing.");
314                     throw new RuntimeException("removeHoldPendingPayment() User " + user.getPrincipalId() + " does not have rights to hold payments. This should not happen unless user is URL spoofing.");
315                 }
316 
317                 changeStatus(paymentGroup, PdpConstants.PaymentStatusCodes.OPEN, PdpConstants.PaymentChangeCodes.REMOVE_HOLD_CHNG_CD, note, user);
318 
319                 LOG.debug("removeHoldPendingPayment() Pending payment was taken off hold; exit method.");
320             }
321             else {
322                 if (LOG.isDebugEnabled()) {
323                     LOG.debug("removeHoldPendingPayment() Payment status is " + paymentStatus + "; cannot remove hold on payment in this status");
324                 }
325 
326                 GlobalVariables.getMessageMap().putError(OLEConstants.GLOBAL_ERRORS, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_PAYMENT_INVALID_STATUS_TO_REMOVE_HOLD);
327                 return false;
328             }
329         }
330         else {
331             LOG.debug("removeHoldPendingPayment() Pending payment group has already been un-held; exit method.");
332         }
333         return true;
334     }
335 
336     /**
337      * @see org.kuali.ole.pdp.document.service.PaymentMaintenanceService#changeImmediateFlag(java.lang.Integer, java.lang.String,
338      *      org.kuali.rice.kim.api.identity.Person)
339      */
340     @Override
341     public void changeImmediateFlag(Integer paymentGroupId, String note, Person user) {
342         // All actions must be performed on entire group not individual detail record
343         if (LOG.isDebugEnabled()) {
344             LOG.debug("changeImmediateFlag() Enter method to hold pending payment with id = " + paymentGroupId);
345         }
346 
347         if (!pdpAuthorizationService.hasSetAsImmediatePayPermission(user.getPrincipalId())) {
348             LOG.warn("changeImmediateFlag() User " + user.getPrincipalId() + " does not have rights to set payments as immediate. This should not happen unless user is URL spoofing.");
349             throw new RuntimeException("changeImmediateFlag() User " + user.getPrincipalId() + " does not have rights to payments as immediate. This should not happen unless user is URL spoofing.");
350         }
351 
352         PaymentGroupHistory paymentGroupHistory = new PaymentGroupHistory();
353         PaymentGroup paymentGroup = this.paymentGroupService.get(paymentGroupId);
354 
355         paymentGroupHistory.setOrigProcessImmediate(paymentGroup.getProcessImmediate());
356 
357         if (paymentGroup.getProcessImmediate().equals(Boolean.TRUE)) {
358             paymentGroup.setProcessImmediate(Boolean.FALSE);
359         }
360         else {
361             paymentGroup.setProcessImmediate(Boolean.TRUE);
362         }
363 
364         changeStatus(paymentGroup, paymentGroup.getPaymentStatus().getCode(), PdpConstants.PaymentChangeCodes.CHANGE_IMMEDIATE_CHNG_CD, note, user, paymentGroupHistory);
365 
366         LOG.debug("changeImmediateFlag() exit method.");
367     }
368 
369     /**
370      * @see org.kuali.ole.pdp.document.service.PaymentMaintenanceService#cancelDisbursement(java.lang.Integer, java.lang.Integer,
371      *      java.lang.String, org.kuali.rice.kim.api.identity.Person)
372      */
373     @Override
374     public boolean cancelDisbursement(Integer paymentGroupId, Integer paymentDetailId, String note, Person user) {
375         // All actions must be performed on entire group not individual detail record
376         if (LOG.isDebugEnabled()) {
377             LOG.debug("cancelDisbursement() Enter method to cancel disbursement with id = " + paymentGroupId);
378         }
379 
380         if (!pdpAuthorizationService.hasCancelPaymentPermission(user.getPrincipalId())) {
381             LOG.warn("cancelDisbursement() User " + user.getPrincipalId() + " does not have rights to cancel payments. This should not happen unless user is URL spoofing.");
382             throw new RuntimeException("cancelDisbursement() User " + user.getPrincipalId() + " does not have rights to cancel payments. This should not happen unless user is URL spoofing.");
383         }
384 
385         PaymentGroup paymentGroup = this.paymentGroupService.get(paymentGroupId);
386 
387         if (paymentGroup == null) {
388             LOG.debug("cancelDisbursement() Disbursement not found; throw exception.");
389             GlobalVariables.getMessageMap().putError(OLEConstants.GLOBAL_ERRORS, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_DISBURSEMENT_NOT_FOUND);
390             return false;
391         }
392 
393         // get the target PaymentGroup info
394         PaymentDetail targetPd = getPaymentDetail(paymentDetailId);
395         KualiInteger targetGroupId = targetPd.getPaymentGroupId();
396         PaymentGroup targetPg = getPaymentGroup(targetGroupId);
397         String targetDvTypeCode = targetPg.getDisbursementTypeCode();
398         String targetDvBankCode = targetPg.getBankCode();
399 
400         String paymentStatus = paymentGroup.getPaymentStatus().getCode();
401 
402         if (!(PdpConstants.PaymentStatusCodes.CANCEL_DISBURSEMENT.equals(paymentStatus))) {
403             if (((PdpConstants.PaymentStatusCodes.EXTRACTED.equals(paymentStatus)) && (ObjectUtils.isNotNull(paymentGroup.getDisbursementDate()))) || (PdpConstants.PaymentStatusCodes.PENDING_ACH.equals(paymentStatus))) {
404                 if (LOG.isDebugEnabled()) {
405                     LOG.debug("cancelDisbursement() Payment status is " + paymentStatus + "; continue with cancel.");
406                 }
407 
408                 List<PaymentGroup> allDisbursementPaymentGroups = this.paymentGroupService.getByDisbursementNumber(paymentGroup.getDisbursementNbr().intValue());
409 
410                 for (PaymentGroup element : allDisbursementPaymentGroups) {
411 
412                     // should be the same DV type and the same bank
413                     if (!(element.getDisbursementTypeCode().equalsIgnoreCase(targetDvTypeCode) && element.getBankCode().equalsIgnoreCase(targetDvBankCode))) {
414                         continue;
415                     }
416 
417                     PaymentGroupHistory pgh = new PaymentGroupHistory();
418 
419                     if (!element.getPaymentDetails().get(0).isDisbursementActionAllowed()) {
420                         LOG.warn("cancelDisbursement() Payment does not allow disbursement action. This should not happen unless user is URL spoofing.");
421                         throw new RuntimeException("cancelDisbursement() Payment does not allow disbursement action. This should not happen unless user is URL spoofing.");
422                     }
423 
424                     if ((ObjectUtils.isNotNull(element.getDisbursementType())) && (element.getDisbursementType().getCode().equals(PdpConstants.DisbursementTypeCodes.CHECK))) {
425                         pgh.setPmtCancelExtractStat(Boolean.FALSE);
426                     }
427 
428                     changeStatus(element, PdpConstants.PaymentStatusCodes.CANCEL_DISBURSEMENT, PdpConstants.PaymentChangeCodes.CANCEL_DISBURSEMENT, note, user, pgh);
429 
430                     glPendingTransactionService.generateCancellationGeneralLedgerPendingEntry(element);
431 
432                     // set primary cancel indicator for EPIC to use
433                     // these payment details will be canceled when running processPdpCancelAndPaidJOb
434                     Map<String, KualiInteger> primaryKeys = new HashMap<String, KualiInteger>();
435                     primaryKeys.put(PdpPropertyConstants.PaymentDetail.PAYMENT_DETAIL_PAYMENT_GROUP_ID, element.getId());
436 
437                     PaymentDetail pd = this.businessObjectService.findByPrimaryKey(PaymentDetail.class, primaryKeys);
438                     if (pd != null) {
439                         pd.setPrimaryCancelledPayment(Boolean.TRUE);
440                     }
441 
442                     this.businessObjectService.save(pd);
443                 }
444 
445                 LOG.debug("cancelDisbursement() Disbursement cancelled; exit method.");
446             }
447             else {
448                 if (LOG.isDebugEnabled()) {
449                     LOG.debug("cancelDisbursement() Payment status is " + paymentStatus + " and disbursement date is " + paymentGroup.getDisbursementDate() + "; cannot cancel payment in this status");
450                 }
451 
452                 GlobalVariables.getMessageMap().putError(OLEConstants.GLOBAL_ERRORS, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_DISBURSEMENT_INVALID_TO_CANCEL);
453                 return false;
454             }
455         }
456         else {
457             LOG.debug("cancelDisbursement() Disbursement has already been cancelled; exit method.");
458         }
459         return true;
460     }
461 
462     /**
463      * @see org.kuali.ole.pdp.document.service.PaymentMaintenanceService#reissueDisbursement(java.lang.Integer,
464      *      java.lang.String, org.kuali.rice.kim.api.identity.Person)
465      */
466     @Override
467     public boolean reissueDisbursement(Integer paymentGroupId, String note, Person user) {
468         // All actions must be performed on entire group not individual detail record
469         if (LOG.isDebugEnabled()) {
470             LOG.debug("reissueDisbursement() Enter method to reissue disbursement with id = " + paymentGroupId);
471         }
472 
473 
474         PaymentGroup paymentGroup = this.paymentGroupService.get(paymentGroupId);
475         if (paymentGroup == null) {
476             LOG.debug("reissueDisbursement() Disbursement not found; throw exception.");
477             GlobalVariables.getMessageMap().putError(OLEConstants.GLOBAL_ERRORS, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_DISBURSEMENT_NOT_FOUND);
478             return false;
479         }
480 
481         String paymentStatus = paymentGroup.getPaymentStatus().getCode();
482 
483         if (!(PdpConstants.PaymentStatusCodes.OPEN.equals(paymentStatus))) {
484             if (((PdpConstants.PaymentStatusCodes.CANCEL_DISBURSEMENT.equals(paymentStatus)) && (ObjectUtils.isNotNull(paymentGroup.getDisbursementDate())))) {
485                 if (LOG.isDebugEnabled()) {
486                     LOG.debug("reissueDisbursement() Payment status is " + paymentStatus + "; continue with reissue.");
487                 }
488 
489                 List<PaymentGroup> allDisbursementPaymentGroups = this.paymentGroupService.getByDisbursementNumber(paymentGroup.getDisbursementNbr().intValue());
490 
491                 for (PaymentGroup pg : allDisbursementPaymentGroups) {
492                     PaymentGroupHistory pgh = new PaymentGroupHistory();
493 
494                     if (!pg.getPaymentDetails().get(0).isDisbursementActionAllowed()) {
495                         LOG.warn("cancelDisbursement() Payment does not allow disbursement action. This should not happen unless user is URL spoofing.");
496                         throw new RuntimeException("cancelDisbursement() Payment does not allow disbursement action. This should not happen unless user is URL spoofing.");
497                     }
498 
499 
500                     pgh.setOrigProcessImmediate(pg.getProcessImmediate());
501                     pgh.setOrigPmtSpecHandling(pg.getPymtSpecialHandling());
502                     pgh.setBank(pg.getBank());
503                     pgh.setOrigPaymentDate(pg.getPaymentDate());
504                     //put a check for null since disbursement date was not set in testMode / dev
505                     if (ObjectUtils.isNotNull(pg.getDisbursementDate())) {
506                         pgh.setOrigDisburseDate(new Timestamp(pg.getDisbursementDate().getTime()));
507                     }
508                     pgh.setOrigAchBankRouteNbr(pg.getAchBankRoutingNbr());
509                     pgh.setOrigDisburseNbr(pg.getDisbursementNbr());
510                     pgh.setOrigAdviceEmail(pg.getAdviceEmailAddress());
511                     pgh.setDisbursementType(pg.getDisbursementType());
512                     pgh.setProcess(pg.getProcess());
513 
514                    // glPendingTransactionService.generateReissueGeneralLedgerPendingEntry(pg);
515 
516                     if (LOG.isDebugEnabled()) {
517                         LOG.debug("cancelReissueDisbursement() Status is '" + paymentStatus + "; delete row from AchAccountNumber table.");
518                     }
519 
520                     AchAccountNumber achAccountNumber = pg.getAchAccountNumber();
521 
522                     if (ObjectUtils.isNotNull(achAccountNumber)) {
523                         this.businessObjectService.delete(achAccountNumber);
524                         pg.setAchAccountNumber(null);
525                     }
526 
527                     // if bank functionality is not enabled or the group bank is inactive clear bank code
528                     if (!bankService.isBankSpecificationEnabled() || !pg.getBank().isActive()) {
529                         pg.setBank(null);
530                     }
531 
532                     pg.setDisbursementDate((java.sql.Date) null);
533                     pg.setAchBankRoutingNbr(null);
534                     pg.setAchAccountType(null);
535                     pg.setPhysCampusProcessCd(null);
536                     pg.setDisbursementNbr((KualiInteger) null);
537                     pg.setAdviceEmailAddress(null);
538                     pg.setDisbursementType(null);
539                     pg.setProcess(null);
540                     pg.setProcessImmediate(false);
541                     changeStatus(pg, PdpConstants.PaymentStatusCodes.OPEN, PdpConstants.PaymentChangeCodes.REISSUE_DISBURSEMENT, note, user, pgh);
542                 }
543 
544                 LOG.debug("reissueDisbursement() Disbursement reissued; exit method.");
545             }
546             else {
547                 if (LOG.isDebugEnabled()) {
548                     LOG.debug("cancelReissueDisbursement() Payment status is " + paymentStatus + " and disbursement date is " + paymentGroup.getDisbursementDate() + "; cannot cancel payment");
549                 }
550 
551                 GlobalVariables.getMessageMap().putError(OLEConstants.GLOBAL_ERRORS, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_DISBURSEMENT_INVALID_TO_CANCEL_AND_REISSUE);
552                 return false;
553             }
554         }
555         else {
556             LOG.debug("cancelReissueDisbursement() Disbursement already cancelled and reissued; exit method.");
557         }
558         return true;
559     }
560 
561     /**
562      * @see org.kuali.ole.pdp.document.service.PaymentMaintenanceService#cancelReissueDisbursement(java.lang.Integer,
563      *      java.lang.String, org.kuali.rice.kim.api.identity.Person)
564      */
565     @Override
566     public boolean cancelReissueDisbursement(Integer paymentGroupId, String note, Person user) {
567         // All actions must be performed on entire group not individual detail record
568         if (LOG.isDebugEnabled()) {
569             LOG.debug("cancelReissueDisbursement() Enter method to cancel disbursement with id = " + paymentGroupId);
570         }
571 
572         if (!pdpAuthorizationService.hasCancelPaymentPermission(user.getPrincipalId())) {
573             LOG.warn("cancelReissueDisbursement() User " + user.getPrincipalId() + " does not have rights to cancel payments. This should not happen unless user is URL spoofing.");
574             throw new RuntimeException("cancelReissueDisbursement() User " + user.getPrincipalId() + " does not have rights to cancel payments. This should not happen unless user is URL spoofing.");
575         }
576 
577         PaymentGroup paymentGroup = this.paymentGroupService.get(paymentGroupId);
578         if (paymentGroup == null) {
579             LOG.debug("cancelReissueDisbursement() Disbursement not found; throw exception.");
580             GlobalVariables.getMessageMap().putError(OLEConstants.GLOBAL_ERRORS, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_DISBURSEMENT_NOT_FOUND);
581             return false;
582         }
583 
584         String paymentStatus = paymentGroup.getPaymentStatus().getCode();
585 
586         if (!(PdpConstants.PaymentStatusCodes.OPEN.equals(paymentStatus))) {
587             if (((PdpConstants.PaymentStatusCodes.EXTRACTED.equals(paymentStatus)) && (ObjectUtils.isNotNull(paymentGroup.getDisbursementDate()))) || (PdpConstants.PaymentStatusCodes.PENDING_ACH.equals(paymentStatus))) {
588                 if (LOG.isDebugEnabled()) {
589                     LOG.debug("cancelReissueDisbursement() Payment status is " + paymentStatus + "; continue with cancel.");
590                 }
591 
592                 List<PaymentGroup> allDisbursementPaymentGroups = this.paymentGroupService.getByDisbursementNumber(paymentGroup.getDisbursementNbr().intValue());
593 
594                 for (PaymentGroup pg : allDisbursementPaymentGroups) {
595                     PaymentGroupHistory pgh = new PaymentGroupHistory();
596 
597                     if (!pg.getPaymentDetails().get(0).isDisbursementActionAllowed()) {
598                         LOG.warn("cancelDisbursement() Payment does not allow disbursement action. This should not happen unless user is URL spoofing.");
599                         throw new RuntimeException("cancelDisbursement() Payment does not allow disbursement action. This should not happen unless user is URL spoofing.");
600                     }
601 
602                     if ((ObjectUtils.isNotNull(pg.getDisbursementType())) && (pg.getDisbursementType().getCode().equals(PdpConstants.DisbursementTypeCodes.CHECK))) {
603                         pgh.setPmtCancelExtractStat(Boolean.FALSE);
604                     }
605 
606                     pgh.setOrigProcessImmediate(pg.getProcessImmediate());
607                     pgh.setOrigPmtSpecHandling(pg.getPymtSpecialHandling());
608                     pgh.setBank(pg.getBank());
609                     pgh.setOrigPaymentDate(pg.getPaymentDate());
610                     //put a check for null since disbursement date was not set in testMode / dev
611                     if (ObjectUtils.isNotNull(pg.getDisbursementDate())) {
612                         pgh.setOrigDisburseDate(new Timestamp(pg.getDisbursementDate().getTime()));
613                     }
614                     pgh.setOrigAchBankRouteNbr(pg.getAchBankRoutingNbr());
615                     pgh.setOrigDisburseNbr(pg.getDisbursementNbr());
616                     pgh.setOrigAdviceEmail(pg.getAdviceEmailAddress());
617                     pgh.setDisbursementType(pg.getDisbursementType());
618                     pgh.setProcess(pg.getProcess());
619 
620                     glPendingTransactionService.generateReissueGeneralLedgerPendingEntry(pg);
621 
622                     if (LOG.isDebugEnabled()) {
623                         LOG.debug("cancelReissueDisbursement() Status is '" + paymentStatus + "; delete row from AchAccountNumber table.");
624                     }
625 
626                     AchAccountNumber achAccountNumber = pg.getAchAccountNumber();
627 
628                     if (ObjectUtils.isNotNull(achAccountNumber)) {
629                         this.businessObjectService.delete(achAccountNumber);
630                         pg.setAchAccountNumber(null);
631                     }
632 
633                     // if bank functionality is not enabled or the group bank is inactive clear bank code
634                     if (!bankService.isBankSpecificationEnabled() || !pg.getBank().isActive()) {
635                         pg.setBank(null);
636                     }
637 
638                     pg.setDisbursementDate((java.sql.Date) null);
639                     pg.setAchBankRoutingNbr(null);
640                     pg.setAchAccountType(null);
641                     pg.setPhysCampusProcessCd(null);
642                     pg.setDisbursementNbr((KualiInteger) null);
643                     pg.setAdviceEmailAddress(null);
644                     pg.setDisbursementType(null);
645                     pg.setProcess(null);
646                     pg.setProcessImmediate(false);
647 
648                     changeStatus(pg, PdpConstants.PaymentStatusCodes.OPEN, PdpConstants.PaymentChangeCodes.CANCEL_REISSUE_DISBURSEMENT, note, user, pgh);
649                 }
650 
651                 LOG.debug("cancelReissueDisbursement() Disbursement cancelled and reissued; exit method.");
652             }
653             else {
654                 if (LOG.isDebugEnabled()) {
655                     LOG.debug("cancelReissueDisbursement() Payment status is " + paymentStatus + " and disbursement date is " + paymentGroup.getDisbursementDate() + "; cannot cancel payment");
656                 }
657 
658                 GlobalVariables.getMessageMap().putError(OLEConstants.GLOBAL_ERRORS, PdpKeyConstants.PaymentDetail.ErrorMessages.ERROR_DISBURSEMENT_INVALID_TO_CANCEL_AND_REISSUE);
659                 return false;
660             }
661         }
662         else {
663             LOG.debug("cancelReissueDisbursement() Disbursement already cancelled and reissued; exit method.");
664         }
665         return true;
666     }
667 
668     /**
669      * Gets DisbursementVoucher by the primary key
670      *
671      * @param paymentDetailId
672      * @return
673      */
674     protected PaymentDetail getPaymentDetail(Integer paymentDetailId) {
675         Map<String, Integer> primaryKeys = new HashMap<String, Integer>();
676         primaryKeys.put(PdpPropertyConstants.PaymentDetail.PAYMENT_ID, paymentDetailId);
677 
678         return this.businessObjectService.findByPrimaryKey(PaymentDetail.class, primaryKeys);
679     }
680 
681     /**
682      * Gets PaymentGroup by the primary key
683      *
684      * @param paymentDetailId
685      * @return
686      */
687     protected PaymentGroup getPaymentGroup(KualiInteger paymentGroupId) {
688         Map<String, KualiInteger> primaryKeys = new HashMap<String, KualiInteger>();
689         primaryKeys.put(PdpPropertyConstants.PaymentGroup.PAYMENT_GROUP_ID, paymentGroupId);
690 
691         return this.businessObjectService.findByPrimaryKey(PaymentGroup.class, primaryKeys);
692     }
693 
694     /**
695      * inject
696      *
697      * @param dao
698      */
699     public void setPaymentGroupDao(PaymentGroupDao dao) {
700         paymentGroupDao = dao;
701     }
702 
703     /**
704      * inject
705      *
706      * @param dao
707      */
708     public void setPaymentDetailDao(PaymentDetailDao dao) {
709         paymentDetailDao = dao;
710     }
711 
712     /**
713      * inject
714      *
715      * @param service
716      */
717     public void setGlPendingTransactionService(PendingTransactionService service) {
718         glPendingTransactionService = service;
719     }
720 
721     /**
722      * inject
723      *
724      * @param service
725      */
726     public void setMailService(MailService mailService) {
727         this.mailService = mailService;
728     }
729 
730     public void setParameterService(ParameterService parameterService) {
731         this.parameterService = parameterService;
732     }
733 
734     /**
735      * Sets the bankService attribute value.
736      *
737      * @param bankService The bankService to set.
738      */
739     public void setBankService(BankService bankService) {
740         this.bankService = bankService;
741     }
742 
743     /**
744      * Sets the business object service
745      *
746      * @param businessObjectService
747      */
748     public void setBusinessObjectService(BusinessObjectService businessObjectService) {
749         this.businessObjectService = businessObjectService;
750     }
751 
752     /**
753      * Sets the payment group service
754      *
755      * @param paymentGroupService
756      */
757     public void setPaymentGroupService(PaymentGroupService paymentGroupService) {
758         this.paymentGroupService = paymentGroupService;
759     }
760 
761     public void setEmailService(PdpEmailService emailService) {
762         this.emailService = emailService;
763     }
764 
765     public void setPdpAuthorizationService(PdpAuthorizationService pdpAuthorizationService) {
766         this.pdpAuthorizationService = pdpAuthorizationService;
767     }
768 }