001/* 002 * The Kuali Financial System, a comprehensive financial management system for higher education. 003 * 004 * Copyright 2005-2014 The Kuali Foundation 005 * 006 * This program is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU Affero General Public License as 008 * published by the Free Software Foundation, either version 3 of the 009 * License, or (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU Affero General Public License for more details. 015 * 016 * You should have received a copy of the GNU Affero General Public License 017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package org.kuali.kfs.pdp.batch.service.impl; 020 021import java.sql.Date; 022import java.util.ArrayList; 023import java.util.Collections; 024import java.util.Iterator; 025import java.util.List; 026import java.util.Map; 027import java.util.Set; 028 029import org.kuali.kfs.integration.purap.PurchasingAccountsPayableModuleService; 030import org.kuali.kfs.pdp.PdpConstants; 031import org.kuali.kfs.pdp.batch.service.ProcessPdpCancelPaidService; 032import org.kuali.kfs.pdp.businessobject.ExtractionUnit; 033import org.kuali.kfs.pdp.businessobject.PaymentDetail; 034import org.kuali.kfs.pdp.service.PaymentDetailService; 035import org.kuali.kfs.pdp.service.PaymentGroupService; 036import org.kuali.kfs.sys.KFSParameterKeyConstants; 037import org.kuali.kfs.sys.batch.service.PaymentSourceToExtractService; 038import org.kuali.kfs.sys.context.SpringContext; 039import org.kuali.kfs.sys.document.PaymentSource; 040import org.kuali.kfs.sys.service.impl.KfsParameterConstants; 041import org.kuali.rice.core.api.datetime.DateTimeService; 042import org.kuali.rice.coreservice.framework.parameter.ParameterService; 043import org.kuali.rice.kew.api.exception.WorkflowException; 044import org.kuali.rice.krad.service.DocumentService; 045import org.springframework.transaction.annotation.Transactional; 046 047/** 048 * Implementation of ProcessPdpCancelPaidService 049 */ 050@Transactional 051public class ProcessPdpCancelPaidServiceImpl implements ProcessPdpCancelPaidService { 052 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ProcessPdpCancelPaidServiceImpl.class); 053 054 protected PaymentGroupService paymentGroupService; 055 protected PaymentDetailService paymentDetailService; 056 protected ParameterService parameterService; 057 protected DateTimeService dateTimeService; 058 protected PurchasingAccountsPayableModuleService purchasingAccountsPayableModuleService; 059 protected DocumentService documentService; 060 061 protected volatile Set<String> paymentSourceCheckACHDocumentTypes; 062 protected volatile List<PaymentSourceToExtractService<PaymentSource>> paymentSourceToExtractServices; 063 064 /** 065 * @see org.kuali.kfs.module.purap.service.ProcessPdpCancelPaidService#processPdpCancels() 066 */ 067 @Override 068 public void processPdpCancels() { 069 LOG.debug("processPdpCancels() started"); 070 071 Date processDate = dateTimeService.getCurrentSqlDate(); 072 073 final List<ExtractionUnit> extractionUnits = getExtractionUnits(); 074 Iterator<PaymentDetail> details = paymentDetailService.getUnprocessedCancelledDetails(extractionUnits); 075 while (details.hasNext()) { 076 PaymentDetail paymentDetail = details.next(); 077 078 String documentTypeCode = paymentDetail.getFinancialDocumentTypeCode(); 079 String documentNumber = paymentDetail.getCustPaymentDocNbr(); 080 081 boolean primaryCancel = paymentDetail.getPrimaryCancelledPayment(); 082 boolean disbursedPayment = PdpConstants.PaymentStatusCodes.CANCEL_DISBURSEMENT.equals(paymentDetail.getPaymentGroup().getPaymentStatusCode()); 083 084 if(purchasingAccountsPayableModuleService.isPurchasingBatchDocument(documentTypeCode)) { 085 purchasingAccountsPayableModuleService.handlePurchasingBatchCancels(documentNumber, documentTypeCode, primaryCancel, disbursedPayment); 086 } 087 else { 088 PaymentSourceToExtractService<PaymentSource> extractService = getPaymentSourceToExtractService(paymentDetail); 089 if (extractService != null) { 090 try { 091 PaymentSource dv = (PaymentSource)getDocumentService().getByDocumentHeaderId(documentNumber); 092 if (dv != null) { 093 if (disbursedPayment || primaryCancel) { 094 extractService.cancelPayment(dv, processDate); 095 } else { 096 extractService.resetFromExtraction(dv); 097 } 098 } 099 } catch (WorkflowException we) { 100 throw new RuntimeException("Could not retrieve document #"+documentNumber, we); 101 } 102 } else { 103 LOG.warn("processPdpCancels() Unknown document type (" + documentTypeCode + ") for document ID: " + documentNumber); 104 continue; 105 } 106 } 107 108 paymentGroupService.processCancelledGroup(paymentDetail.getPaymentGroup(), processDate); 109 } 110 } 111 112 /** 113 * @see org.kuali.kfs.module.purap.service.ProcessPdpCancelPaidService#processPdpPaids() 114 */ 115 @Override 116 public void processPdpPaids() { 117 LOG.debug("processPdpPaids() started"); 118 119 Date processDate = dateTimeService.getCurrentSqlDate(); 120 121 final List<ExtractionUnit> extractionUnits = getExtractionUnits(); 122 Iterator<PaymentDetail> details = paymentDetailService.getUnprocessedPaidDetails(extractionUnits); 123 while (details.hasNext()) { 124 PaymentDetail paymentDetail = details.next(); 125 126 String documentTypeCode = paymentDetail.getFinancialDocumentTypeCode(); 127 String documentNumber = paymentDetail.getCustPaymentDocNbr(); 128 129 if(purchasingAccountsPayableModuleService.isPurchasingBatchDocument(documentTypeCode)) { 130 purchasingAccountsPayableModuleService.handlePurchasingBatchPaids(documentNumber, documentTypeCode, processDate); 131 } 132 else { 133 PaymentSourceToExtractService<PaymentSource> extractService = getPaymentSourceToExtractService(paymentDetail); 134 if (extractService != null) { 135 try { 136 PaymentSource dv = (PaymentSource)getDocumentService().getByDocumentHeaderId(documentNumber); 137 extractService.markAsPaid(dv, processDate); 138 } catch (WorkflowException we) { 139 throw new RuntimeException("Could not retrieve document #"+documentNumber, we); 140 } 141 } else { 142 LOG.warn("processPdpPaids() Unknown document type (" + documentTypeCode + ") for document ID: " + documentNumber); 143 continue; 144 } 145 } 146 147 paymentGroupService.processPaidGroup(paymentDetail.getPaymentGroup(), processDate); 148 } 149 } 150 151 /** 152 * @see org.kuali.kfs.module.purap.service.ProcessPdpCancelPaidService#processPdpCancelsAndPaids() 153 */ 154 @Override 155 public void processPdpCancelsAndPaids() { 156 LOG.debug("processPdpCancelsAndPaids() started"); 157 158 processPdpCancels(); 159 processPdpPaids(); 160 } 161 162 /** 163 * @return a List of all available PaymentSourceToExtractService implementations 164 */ 165 protected List<PaymentSourceToExtractService<PaymentSource>> getPaymentSourceToExtractServices() { 166 if (paymentSourceToExtractServices == null) { 167 paymentSourceToExtractServices = new ArrayList<PaymentSourceToExtractService<PaymentSource>>(); 168 Map<String, PaymentSourceToExtractService> extractionServices = SpringContext.getBeansOfType(PaymentSourceToExtractService.class); 169 for (PaymentSourceToExtractService<PaymentSource> extractionService : extractionServices.values()) { 170 paymentSourceToExtractServices.add(extractionService); 171 } 172 } 173 return paymentSourceToExtractServices; 174 } 175 176 /** 177 * Looks up the PaymentSourceToExtractService which can act upon the given PaymentDetail, based on the PaymentDetail's document type 178 * @param paymentDetail the payment detail to find an extraction service to act upon 179 * @return the matching PaymentSourceToExtractService, or null if a matching service could not be found (which would be weird, because _something_ created this PaymentDetail, but...whatever) 180 */ 181 protected PaymentSourceToExtractService<PaymentSource> getPaymentSourceToExtractService(PaymentDetail paymentDetail) { 182 for (PaymentSourceToExtractService<PaymentSource> extractionService : getPaymentSourceToExtractServices()) { 183 if (extractionService.handlesAchCheckDocumentType(paymentDetail.getFinancialDocumentTypeCode())) { 184 return extractionService; 185 } 186 } 187 return null; 188 } 189 190 /** 191 * Loops through the PaymentSourceToExtractService List and builds ExtractionUnits for each 192 * @return a List of ExtractionUnits for each customer profile organization and sub-organization handled by PaymentSourceToExtractServices 193 */ 194 protected List<ExtractionUnit> getExtractionUnitsForPaymentSourceToExtractServices() { 195 List<ExtractionUnit> extractionUnits = new ArrayList<ExtractionUnit>(); 196 for (PaymentSourceToExtractService<PaymentSource> extractionService : getPaymentSourceToExtractServices()) { 197 final ExtractionUnit extractionUnit = new ExtractionUnit(extractionService.getPreDisbursementCustomerProfileUnit(), extractionService.getPreDisbursementCustomerProfileSubUnit()); 198 if (!extractionUnits.contains(extractionUnit)) { 199 extractionUnits.add(extractionUnit); 200 } 201 } 202 return extractionUnits; 203 } 204 205 /** 206 * @return a List of all known ExtractionUnits 207 */ 208 protected List<ExtractionUnit> getExtractionUnits() { 209 List<ExtractionUnit> extractionUnits = getExtractionUnitsForPaymentSourceToExtractServices(); 210 final String purapOrg = parameterService.getParameterValueAsString(KfsParameterConstants.PURCHASING_BATCH.class, KFSParameterKeyConstants.PurapPdpParameterConstants.PURAP_PDP_ORG_CODE); 211 final String purapSubUnit = parameterService.getParameterValueAsString(KfsParameterConstants.PURCHASING_BATCH.class, KFSParameterKeyConstants.PurapPdpParameterConstants.PURAP_PDP_SUB_UNIT_CODE); 212 final ExtractionUnit purapExtractionUnit = new ExtractionUnit(purapOrg, purapSubUnit); 213 extractionUnits.add(purapExtractionUnit); 214 return Collections.unmodifiableList(extractionUnits); 215 } 216 217 public void setPaymentDetailService(PaymentDetailService paymentDetailService) { 218 this.paymentDetailService = paymentDetailService; 219 } 220 221 public void setPaymentGroupService(PaymentGroupService paymentGroupService) { 222 this.paymentGroupService = paymentGroupService; 223 } 224 225 public void setParameterService(ParameterService parameterService) { 226 this.parameterService = parameterService; 227 } 228 229 public void setPurchasingAccountsPayableModuleService(PurchasingAccountsPayableModuleService purchasingAccountsPayableModuleService) { 230 this.purchasingAccountsPayableModuleService = purchasingAccountsPayableModuleService; 231 } 232 233 public void setDateTimeService(DateTimeService dts) { 234 this.dateTimeService = dts; 235 } 236 237 /** 238 * @return the implementation of the DocumentService to use 239 */ 240 public DocumentService getDocumentService() { 241 return documentService; 242 } 243 244 /** 245 * Sets the implementation of the DocumentService to use 246 * @param documentService the implementation of the DocumentService to use 247 */ 248 public void setDocumentService(DocumentService documentService) { 249 this.documentService = documentService; 250 } 251 252}